You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
163 lines
4.1 KiB
163 lines
4.1 KiB
'use strict';
|
|
|
|
var _ = require('lodash');
|
|
var BN = require('../crypto/bn');
|
|
var buffer = require('buffer');
|
|
var bufferUtil = require('../util/buffer');
|
|
var JSUtil = require('../util/js');
|
|
var BufferWriter = require('../encoding/bufferwriter');
|
|
var Script = require('../script');
|
|
var $ = require('../util/preconditions');
|
|
var errors = require('../errors');
|
|
|
|
var MAX_SAFE_INTEGER = 0x1fffffffffffff;
|
|
|
|
function Output(args) {
|
|
if (!(this instanceof Output)) {
|
|
return new Output(args);
|
|
}
|
|
if (JSUtil.isValidJSON(args)) {
|
|
return Output.fromJSON(args);
|
|
} else if (_.isObject(args)) {
|
|
this.satoshis = args.satoshis;
|
|
if (_.isString(args.script) && JSUtil.isHexa(args.script)) {
|
|
args.script = new buffer.Buffer(args.script, 'hex');
|
|
}
|
|
this.setScript(args.script);
|
|
} else {
|
|
throw new TypeError('Unrecognized argument for Output');
|
|
}
|
|
}
|
|
|
|
Object.defineProperty(Output.prototype, 'script', {
|
|
configurable: false,
|
|
enumerable: true,
|
|
get: function() {
|
|
return this._script;
|
|
}
|
|
});
|
|
|
|
Object.defineProperty(Output.prototype, 'satoshis', {
|
|
configurable: false,
|
|
enumerable: true,
|
|
get: function() {
|
|
return this._satoshis;
|
|
},
|
|
set: function(num) {
|
|
if (num instanceof BN) {
|
|
this._satoshisBN = num;
|
|
this._satoshis = num.toNumber();
|
|
} else if (_.isString(num)) {
|
|
this._satoshis = parseInt(num);
|
|
this._satoshisBN = BN.fromNumber(this._satoshis);
|
|
} else {
|
|
$.checkArgument(
|
|
JSUtil.isNaturalNumber(num),
|
|
'Output satoshis is not a natural number'
|
|
);
|
|
this._satoshisBN = BN.fromNumber(num);
|
|
this._satoshis = num;
|
|
}
|
|
$.checkState(
|
|
JSUtil.isNaturalNumber(this._satoshis),
|
|
'Output satoshis is not a natural number'
|
|
);
|
|
}
|
|
});
|
|
|
|
Output.prototype.invalidSatoshis = function() {
|
|
if (this._satoshis > MAX_SAFE_INTEGER) {
|
|
return 'transaction txout satoshis greater than max safe integer';
|
|
}
|
|
if (this._satoshis !== this._satoshisBN.toNumber()) {
|
|
return 'transaction txout satoshis has corrupted value';
|
|
}
|
|
if (this._satoshis < 0) {
|
|
return 'transaction txout negative';
|
|
}
|
|
return false;
|
|
};
|
|
|
|
Output.prototype.toObject = function toObject() {
|
|
var obj = {
|
|
satoshis: this.satoshis
|
|
};
|
|
obj.script = this._scriptBuffer.toString('hex');
|
|
return obj;
|
|
};
|
|
|
|
Output.prototype.toJSON = function toJSON() {
|
|
return JSON.stringify(this.toObject());
|
|
};
|
|
|
|
Output.fromJSON = function(data) {
|
|
$.checkArgument(JSUtil.isValidJSON(data), 'data must be valid JSON');
|
|
var json = JSON.parse(data);
|
|
return new Output({
|
|
satoshis: Number(json.satoshis),
|
|
script: new Script(json.script)
|
|
});
|
|
};
|
|
|
|
Output.prototype.setScriptFromBuffer = function(buffer) {
|
|
this._scriptBuffer = buffer;
|
|
try {
|
|
this._script = Script.fromBuffer(this._scriptBuffer);
|
|
} catch(e) {
|
|
if (e instanceof errors.Script.InvalidBuffer) {
|
|
this._script = null;
|
|
} else {
|
|
throw e;
|
|
}
|
|
}
|
|
};
|
|
|
|
Output.prototype.setScript = function(script) {
|
|
if (script instanceof Script) {
|
|
this._scriptBuffer = script.toBuffer();
|
|
this._script = script;
|
|
} else if (_.isString(script)) {
|
|
this._script = Script.fromString(script);
|
|
this._scriptBuffer = this._script.toBuffer();
|
|
} else if (bufferUtil.isBuffer(script)) {
|
|
this.setScriptFromBuffer(script);
|
|
} else {
|
|
throw new TypeError('Invalid argument type: script');
|
|
}
|
|
return this;
|
|
};
|
|
|
|
Output.prototype.inspect = function() {
|
|
var scriptStr;
|
|
if (this.script) {
|
|
scriptStr = this.script.inspect();
|
|
} else {
|
|
scriptStr = this._scriptBuffer.toString('hex');
|
|
}
|
|
return '<Output (' + this.satoshis + ' sats) ' + scriptStr + '>';
|
|
};
|
|
|
|
Output.fromBufferReader = function(br) {
|
|
var obj = {};
|
|
obj.satoshis = br.readUInt64LEBN();
|
|
var size = br.readVarintNum();
|
|
if (size !== 0) {
|
|
obj.script = br.read(size);
|
|
} else {
|
|
obj.script = new buffer.Buffer([]);
|
|
}
|
|
return new Output(obj);
|
|
};
|
|
|
|
Output.prototype.toBufferWriter = function(writer) {
|
|
if (!writer) {
|
|
writer = new BufferWriter();
|
|
}
|
|
writer.writeUInt64LEBN(this._satoshisBN);
|
|
var script = this._scriptBuffer;
|
|
writer.writeVarintNum(script.length);
|
|
writer.write(script);
|
|
return writer;
|
|
};
|
|
|
|
module.exports = Output;
|
|
|