UNPKG

@meterio/devkit

Version:

Typescript library to aid DApp development on Meter network

238 lines 17.3 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.Transaction = void 0; const address_1 = require("./cry/address"); const blake2b_1 = require("./cry/blake2b"); const secp256k1_1 = require("./cry/secp256k1"); const rlp_1 = require("./rlp"); /** Transaction class defines Meter's multi-clause transaction */ class Transaction { /** decode from Buffer to transaction * @param raw encoded buffer * @param unsigned to indicator if the encoded buffer contains signature */ static decode(raw, unsigned) { let body; let signature; if (unsigned) { body = unsignedTxRLP.decode(raw); } else { const decoded = txRLP.decode(raw); signature = decoded.signature; delete decoded.signature; body = decoded; } const reserved = body.reserved; if (reserved.length > 0) { if (reserved[reserved.length - 1].length === 0) { throw new Error('invalid reserved fields: not trimmed'); } const features = featuresKind.buffer(reserved[0], 'reserved.features').decode(); body.reserved = { features, }; if (reserved.length > 1) { body.reserved.unused = reserved.slice(1); } } else { delete body.reserved; } const tx = new Transaction(body); if (signature) { tx.signature = signature; } return tx; } /** * construct a transaction object with given body * @param body body of tx */ constructor(body) { this.body = Object.assign({}, body); } /** * returns transaction ID * null returned if something wrong (e.g. invalid signature) */ get id() { if (!this._signatureValid) { return null; } try { const signingHash = this.signingHash(); const pubKey = secp256k1_1.secp256k1.recover(signingHash, this.signature.slice(0, 65)); const origin = (0, address_1.publicKeyToAddress)(pubKey); return '0x' + (0, blake2b_1.blake2b256)(signingHash, origin).toString('hex'); } catch (_a) { return null; } } /** * compute signing hashes. * It returns tx hash for origin or delegator depends on param `delegateFor`. * @param delegateFor address of intended tx origin. If set, the returned hash is for delegator to sign. */ signingHash(delegateFor) { const reserved = this._encodeReserved(); const buf = unsignedTxRLP.encode(Object.assign(Object.assign({}, this.body), { reserved })); const hash = (0, blake2b_1.blake2b256)(buf); if (delegateFor) { if (!/^0x[0-9a-f]{40}$/i.test(delegateFor)) { throw new Error('delegateFor expected address'); } return (0, blake2b_1.blake2b256)(hash, Buffer.from(delegateFor.slice(2), 'hex')); } return hash; } /** returns tx origin. null returned if no signature or not incorrectly signed */ get origin() { if (!this._signatureValid) { return null; } try { const signingHash = this.signingHash(); const pubKey = secp256k1_1.secp256k1.recover(signingHash, this.signature.slice(0, 65)); return '0x' + (0, address_1.publicKeyToAddress)(pubKey).toString('hex'); } catch (_a) { return null; } } /** returns tx delegator. null returned if no signature or not incorrectly signed */ get delegator() { if (!this.delegated) { return null; } if (!this._signatureValid) { return null; } const origin = this.origin; if (!origin) { return null; } try { const signingHash = this.signingHash(origin); const pubKey = secp256k1_1.secp256k1.recover(signingHash, this.signature.slice(65)); return '0x' + (0, address_1.publicKeyToAddress)(pubKey).toString('hex'); } catch (_a) { return null; } } /** returns whether delegated. see https://github.com/dfinlab/VIPs/blob/master/vips/VIP-191.md */ get delegated() { return ((((this.body.reserved || {}).features || 0) & Transaction.DELEGATED_MASK) === Transaction.DELEGATED_MASK); } /** returns intrinsic gas it takes */ get intrinsicGas() { return Transaction.intrinsicGas(this.body.clauses); } /** encode into Buffer */ encode() { const reserved = this._encodeReserved(); if (this.signature) { return txRLP.encode(Object.assign(Object.assign({}, this.body), { reserved, signature: this.signature })); } return unsignedTxRLP.encode(Object.assign(Object.assign({}, this.body), { reserved })); } _encodeReserved() { const reserved = this.body.reserved || {}; const list = [ featuresKind.data(reserved.features || 0, 'reserved.features').encode(), ...(reserved.unused || []), ]; // trim while (list.length > 0) { if (list[list.length - 1].length === 0) { list.pop(); } else { break; } } return list; } get _signatureValid() { const expectedSigLen = this.delegated ? 65 * 2 : 65; return this.signature ? this.signature.length === expectedSigLen : false; } } Transaction.DELEGATED_MASK = 1; exports.Transaction = Transaction; (function (Transaction) { /** * calculates intrinsic gas that a tx costs with the given clauses. * @param clauses */ function intrinsicGas(clauses) { const txGas = 5000; const clauseGas = 16000; const clauseGasContractCreation = 48000; if (clauses.length === 0) { return txGas + clauseGas; } return clauses.reduce((sum, c) => { if (c.to) { sum += clauseGas; } else { sum += clauseGasContractCreation; } sum += dataGas(c.data); return sum; }, txGas); } Transaction.intrinsicGas = intrinsicGas; function dataGas(data) { const zgas = 4; const nzgas = 68; let sum = 0; for (let i = 2; i < data.length; i += 2) { if (data.substr(i, 2) === '00') { sum += zgas; } else { sum += nzgas; } } return sum; } })(Transaction = exports.Transaction || (exports.Transaction = {})); exports.Transaction = Transaction; const unsignedTxRLP = new rlp_1.RLP({ name: 'tx', kind: [ { name: 'chainTag', kind: new rlp_1.RLP.NumericKind(1) }, { name: 'blockRef', kind: new rlp_1.RLP.CompactFixedBlobKind(8) }, { name: 'expiration', kind: new rlp_1.RLP.NumericKind(4) }, { name: 'clauses', kind: { item: [ { name: 'to', kind: new rlp_1.RLP.NullableFixedBlobKind(20) }, { name: 'value', kind: new rlp_1.RLP.NumericKind(32) }, { name: 'token', kind: new rlp_1.RLP.NumericKind(1) }, { name: 'data', kind: new rlp_1.RLP.BlobKind() }, ], }, }, { name: 'gasPriceCoef', kind: new rlp_1.RLP.NumericKind(1) }, { name: 'gas', kind: new rlp_1.RLP.NumericKind(8) }, { name: 'dependsOn', kind: new rlp_1.RLP.NullableFixedBlobKind(32) }, { name: 'nonce', kind: new rlp_1.RLP.NumericKind(8) }, { name: 'reserved', kind: { item: new rlp_1.RLP.BufferKind() } }, ], }); const txRLP = new rlp_1.RLP({ name: 'tx', kind: [ ...unsignedTxRLP.profile.kind, { name: 'signature', kind: new rlp_1.RLP.BufferKind() }, ], }); const featuresKind = new rlp_1.RLP.NumericKind(4); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHJhbnNhY3Rpb24uanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvdHJhbnNhY3Rpb24udHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBQUEsMkNBQW1EO0FBQ25ELDJDQUEyQztBQUMzQywrQ0FBNEM7QUFDNUMsK0JBQTRCO0FBRTVCLGlFQUFpRTtBQUNqRSxNQUFhLFdBQVc7SUFHdEI7OztPQUdHO0lBQ0ksTUFBTSxDQUFDLE1BQU0sQ0FBQyxHQUFXLEVBQUUsUUFBa0I7UUFDbEQsSUFBSSxJQUFzQixDQUFDO1FBQzNCLElBQUksU0FBNkIsQ0FBQztRQUNsQyxJQUFJLFFBQVEsRUFBRTtZQUNaLElBQUksR0FBRyxhQUFhLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDO1NBQ2xDO2FBQU07WUFDTCxNQUFNLE9BQU8sR0FBRyxLQUFLLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDO1lBQ2xDLFNBQVMsR0FBRyxPQUFPLENBQUMsU0FBbUIsQ0FBQztZQUN4QyxPQUFPLE9BQU8sQ0FBQyxTQUFTLENBQUM7WUFDekIsSUFBSSxHQUFHLE9BQU8sQ0FBQztTQUNoQjtRQUVELE1BQU0sUUFBUSxHQUFHLElBQUksQ0FBQyxRQUFvQixDQUFDO1FBQzNDLElBQUksUUFBUSxDQUFDLE1BQU0sR0FBRyxDQUFDLEVBQUU7WUFDdkIsSUFBSSxRQUFRLENBQUMsUUFBUSxDQUFDLE1BQU0sR0FBRyxDQUFDLENBQUMsQ0FBQyxNQUFNLEtBQUssQ0FBQyxFQUFFO2dCQUM5QyxNQUFNLElBQUksS0FBSyxDQUFDLHNDQUFzQyxDQUFDLENBQUM7YUFDekQ7WUFFRCxNQUFNLFFBQVEsR0FBRyxZQUFZLENBQUMsTUFBTSxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUMsRUFBRSxtQkFBbUIsQ0FBQyxDQUFDLE1BQU0sRUFBWSxDQUFDO1lBQzFGLElBQUksQ0FBQyxRQUFRLEdBQUc7Z0JBQ2QsUUFBUTthQUNULENBQUM7WUFDRixJQUFJLFFBQVEsQ0FB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QUMsRUFBRSxDQUFDLEVBQUU7UUFDOUQsRUFBRSxJQUFJLEVBQUUsT0FBTyxFQUFFLElBQUksRUFBRSxJQUFJLFNBQUcsQ0FBQyxXQUFXLENBQUMsQ0FBQyxDQUFDLEVBQUU7UUFDL0MsRUFBRSxJQUFJLEVBQUUsVUFBVSxFQUFFLElBQUksRUFBRSxFQUFFLElBQUksRUFBRSxJQUFJLFNBQUcsQ0FBQyxVQUFVLEVBQUUsRUFBRSxFQUFFO0tBQzNEO0NBQ0YsQ0FBQyxDQUFDO0FBRUgsTUFBTSxLQUFLLEdBQUcsSUFBSSxTQUFHLENBQUM7SUFDcEIsSUFBSSxFQUFFLElBQUk7SUFDVixJQUFJLEVBQUU7UUFDSixHQUFJLGFBQWEsQ0FBQyxPQUFPLENBQUMsSUFBc0I7UUFDaEQsRUFBRSxJQUFJLEVBQUUsV0FBVyxFQUFFLElBQUksRUFBRSxJQUFJLFNBQUcsQ0FBQyxVQUFVLEVBQUUsRUFBRTtLQUNsRDtDQUNGLENBQUMsQ0FBQztBQUVILE1BQU0sWUFBWSxHQUFHLElBQUksU0FBRyxDQUFDLFdBQVcsQ0FBQyxDQUFDLENBQUMsQ0FBQyJ9