parsec-lib
Version:
transaction and block implementation
246 lines (201 loc) • 15.4 kB
JavaScript
'use strict';Object.defineProperty(exports, "__esModule", { value: true });exports.SPEND_INPUT_LENGTH = undefined;var _extends = Object.assign || function (target) {for (var i = 1; i < arguments.length; i++) {var source = arguments[i];for (var key in source) {if (Object.prototype.hasOwnProperty.call(source, key)) {target[key] = source[key];}}}return target;};var _createClass = function () {function defineProperties(target, props) {for (var i = 0; i < props.length; i++) {var descriptor = props[i];descriptor.enumerable = descriptor.enumerable || false;descriptor.configurable = true;if ("value" in descriptor) descriptor.writable = true;Object.defineProperty(target, descriptor.key, descriptor);}}return function (Constructor, protoProps, staticProps) {if (protoProps) defineProperties(Constructor.prototype, protoProps);if (staticProps) defineProperties(Constructor, staticProps);return Constructor;};}();
/**
* Copyright (c) 2018-present, Parsec Labs (parseclabs.org)
*
* This source code is licensed under the GNU Affero General Public License,
* version 3, found in the LICENSE file in the root directory of this source
* tree.
*/
var _assert = require('assert');var _assert2 = _interopRequireDefault(_assert);
var _ethereumjsUtil = require('ethereumjs-util');var _ethereumjsUtil2 = _interopRequireDefault(_ethereumjsUtil);
var _outpoint = require('./outpoint');var _outpoint2 = _interopRequireDefault(_outpoint);
var _util = require('./util');var _util2 = _interopRequireDefault(_util);
var _type = require('./type');var _type2 = _interopRequireDefault(_type);function _interopRequireDefault(obj) {return obj && obj.__esModule ? obj : { default: obj };}function _classCallCheck(instance, Constructor) {if (!(instance instanceof Constructor)) {throw new TypeError("Cannot call a class as a function");}}
// outpoint(32 bytes prev tx + 1 byte output pos) + 65 bytes signature
var SPEND_INPUT_LENGTH = exports.SPEND_INPUT_LENGTH = 33 + 65;var
Input = function () {
function Input(options) {_classCallCheck(this, Input);
if (_outpoint2.default.isOutpoint(options)) {
this.prevout = options;
} else if (_util2.default.isU32(options)) {
this.depositId = options;
} else if (options && options.script) {
this.type = _type2.default.SPEND_COND;
this.script = options.script;
if (!Buffer.isBuffer(options.script)) {
this.script = _ethereumjsUtil2.default.toBuffer(options.script);
}
this.gasPrice = options.gasPrice;
this.prevout = options.prevout;
if (options.msgData) {
this.msgData = options.msgData;
if (!Buffer.isBuffer(options.msgData)) {
this.msgData = _ethereumjsUtil2.default.toBuffer(options.msgData);
}
}
} else if (options && options.prevout) {
this.type = options.type;
this.prevout = options.prevout;
}
}_createClass(Input, [{ key: 'setSigner', value: function setSigner(
signer) {
this.signer = signer;
} }, { key: 'isConsolidation', value: function isConsolidation()
{
return this.type === _type2.default.CONSOLIDATE;
} }, { key: 'isDeposit', value: function isDeposit()
{
return this.depositId;
} }, { key: 'isSpend', value: function isSpend()
{
return this.prevout;
}
/**
* Calculate size of input.
* @returns {Number}
*/ }, { key: 'getSize', value: function getSize()
{
if (this.isDeposit()) {
return 4;
}
if (this.isConsolidation()) {
return 33;
}
if (this.type === _type2.default.SPEND_COND) {
// prevout + gasPrice + 2 bytes msgData length + msgData
// + 2 bytees script length + script
var rv = 33 + 4 + 2 + 2 + this.script.length;
rv += this.msgData ? this.msgData.length : 0;
return rv;
}
if (this.isSpend()) {
return SPEND_INPUT_LENGTH;
}
return 0;
} }, { key: 'setSig', value: function setSig(
r, s, v, signer) {
(0, _assert2.default)(this.isSpend(), 'Can only set signature on outpoint');
(0, _assert2.default)(Buffer.isBuffer(r), 'r has to be buffer');
(0, _assert2.default)(r.length === 32, 'r length must be 32 bytes.');
this.r = r;
(0, _assert2.default)(Buffer.isBuffer(s), 's has to be buffer');
(0, _assert2.default)(s.length === 32, 's length must be 32 bytes.');
this.s = s;
(0, _assert2.default)(_util2.default.isU8(v), 'v must be a uint8.');
this.v = v;
if (signer) {
(0, _assert2.default)(typeof signer === 'string', 'signer must be a string');
this.signer = signer;
}
} }, { key: 'setMsgData', value: function setMsgData(
msgData) {
(0, _assert2.default)(this.type === _type2.default.SPEND_COND, 'Can only set msgData on SPEND_COND');
this.msgData = msgData;
if (!Buffer.isBuffer(msgData)) {
this.msgData = _ethereumjsUtil2.default.toBuffer(msgData);
}
} }, { key: 'recoverSigner', value: function recoverSigner(
sigHashBuf) {
(0, _assert2.default)(this.v, 'Input should be signed');
(0, _assert2.default)(sigHashBuf, 'sigHashBuf is required');
this.signer = Input.recoverSignerAddress(sigHashBuf, this.v, this.r, this.s);
} }, { key: 'toJSON', value: function toJSON()
{
if (this.isDeposit()) {
return {
depositId: this.depositId };
}
if (this.type === _type2.default.SPEND_COND) {
var input = _extends({}, this.prevout);
input.hash = _ethereumjsUtil2.default.bufferToHex(input.hash);
input.msgData = _ethereumjsUtil2.default.bufferToHex(this.msgData);
input.script = _ethereumjsUtil2.default.bufferToHex(this.script);
input.gasPrice = this.gasPrice;
return input;
}
if (this.isConsolidation()) {
var _input = _extends({}, this.prevout, { type: this.type });
_input.hash = _ethereumjsUtil2.default.bufferToHex(_input.hash);
return _input;
}
if (this.isSpend()) {
var _input2 = _extends({}, this.prevout);
_input2.hash = _ethereumjsUtil2.default.bufferToHex(_input2.hash);
if (this.signer) {
_input2.r = _ethereumjsUtil2.default.bufferToHex(this.r);
_input2.s = _ethereumjsUtil2.default.bufferToHex(this.s);
_input2.v = this.v;
_input2.signer = this.signer;
}
return _input2;
}
return {};
}
/**
* Instantiate input from json object.
* @param {Object} json
* @returns {Input}
*/ }, { key: 'toRaw', value: function toRaw()
{
var dataBuf = Buffer.alloc(this.getSize());
if (this.isDeposit()) {
dataBuf.writeUInt32BE(this.depositId);
} else if (this.type === _type2.default.SPEND_COND) {
this.prevout.toRaw(dataBuf, 0);
dataBuf.writeUInt32BE(this.gasPrice, 33);
var msgDataLength = this.msgData ? this.msgData.length : 0;
if (msgDataLength) {
dataBuf.writeUInt16BE(this.msgData.length, 37);
this.msgData.copy(dataBuf, 39);
}
dataBuf.writeUInt16BE(this.script.length, 39 + msgDataLength);
this.script.copy(dataBuf, 41 + msgDataLength);
} else if (this.isSpend()) {
this.prevout.toRaw(dataBuf, 0);
if (this.signer) {
this.r.copy(dataBuf, 33);
this.s.copy(dataBuf, 65);
dataBuf.writeInt8(this.v, 97);
}
}
return dataBuf;
}
/**
* Instantiate input from serialized data.
* @param {Buffer} data
* @returns {Input}
*/ }], [{ key: 'fromJSON', value: function fromJSON(json) {(0, _assert2.default)(json, 'Input data is required.');if (json.depositId) {return new Input(json.depositId);}if (json.hash) {var input = new Input(_outpoint2.default.fromJSON(json));if (json.type) {input.type = json.type;}if (json.signer) {input.setSig(_ethereumjsUtil2.default.toBuffer(json.r), _ethereumjsUtil2.default.toBuffer(json.s), json.v, json.signer);}if (json.contractAddr) {input.contractAddr = json.contractAddr;}return input;}return null;} }, { key: 'fromRaw', value: function fromRaw(
buf, offset, sigHashBuf) {
var off = offset || 0;
var prevout = new _outpoint2.default(buf.slice(0 + off, 32 + off), buf.readUInt8(32 + off));
var input = void 0;
if (sigHashBuf === _type2.default.CONSOLIDATE ||
sigHashBuf === _type2.default.COMP_RESP || sigHashBuf === _type2.default.COMP_REQ) {
// nothing
input = new Input({ prevout: prevout, type: sigHashBuf });
} else if (sigHashBuf === _type2.default.SPEND_COND) {
var gasPrice = buf.readUInt32BE(off + 33);
var msgLength = buf.readUInt16BE(off + 37);
var msgData = Buffer.alloc(msgLength);
buf.copy(msgData, 0, off + 39, off + 39 + msgLength);
var scriptLength = buf.readUInt16BE(off + 39 + msgLength);
var script = Buffer.alloc(scriptLength);
buf.copy(script, 0, off + 41 + msgLength, off + 41 + msgLength + scriptLength);
input = new Input({ prevout: prevout, gasPrice: gasPrice, msgData: msgData, script: script, type: sigHashBuf });
} else if (sigHashBuf) {
input = new Input(prevout);
var r = buf.slice(33 + off, 65 + off);
var s = buf.slice(65 + off, 97 + off);
var v = buf.readUInt8(97 + off);
var signer = Input.recoverSignerAddress(sigHashBuf, v, r, s);
input.setSig(r, s, v, signer);
}
return input;
}
// Utils
}, { key: 'recoverSignerAddress', value: function recoverSignerAddress(
sigHashBuf, v, r, s) {
var pubKey = _ethereumjsUtil2.default.ecrecover(sigHashBuf, v, r, s);
var addrBuf = _ethereumjsUtil2.default.pubToAddress(pubKey);
return _ethereumjsUtil2.default.bufferToHex(addrBuf);
} }]);return Input;}();exports.default = Input;