UNPKG

parsec-lib

Version:

transaction and block implementation

246 lines (201 loc) 15.4 kB
'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;