UNPKG

thor-devkit

Version:

Typescript library to aid DApp development on VeChain Thor

315 lines 26.1 kB
import { address } from './address'; import { blake2b256 } from './blake2b'; import { RLP } from './rlp'; import { secp256k1 } from './secp256k1'; import { Buffer } from 'buffer'; /** Transaction class defines VeChainThor's multi-clause transaction */ export 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 type; if (raw.length > 0 && raw[0] > 0x7f) { type = Transaction.Type.Legacy; } else { if (raw.length === 0) { throw new Error('typed transaction too short'); } if (raw[0] === Transaction.Type.DynamicFee) { type = Transaction.Type.DynamicFee; // remove type identifier for subsequent decoding raw = raw.slice(1); } else { throw new Error('transaction type not supported: ' + raw[0]); } } let body; let signature; if (unsigned) { body = type === Transaction.Type.DynamicFee ? unsignedDynamicFeeTxRLP.decode(raw) : unsignedLegacyTxRLP.decode(raw); body.type = type; } else { const decoded = type === Transaction.Type.DynamicFee ? dynamicFeeTxRLP.decode(raw) : legacyTxRLP.decode(raw); signature = decoded.signature; delete decoded.signature; body = decoded; body.type = type; } 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.recover(signingHash, this.signature.slice(0, 65)); const origin = address.fromPublicKey(pubKey); return '0x' + blake2b256(signingHash, Buffer.from(origin.slice(2), 'hex')).toString('hex'); } catch (_a) { return null; } } /** returns transaction type, type legacy will return if type is not set */ get type() { if (this.body.hasOwnProperty('type') && this.body.type !== undefined) { return this.body.type; } return Transaction.Type.Legacy; } /** * 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) { this.checkType(); const reserved = this._encodeReserved(); let buf; if (this.type === Transaction.Type.DynamicFee) { const raw = unsignedDynamicFeeTxRLP.encode(Object.assign(Object.assign({}, this.body), { reserved })); buf = Buffer.concat([Buffer.from([Transaction.Type.DynamicFee]), raw]); } else { buf = unsignedLegacyTxRLP.encode(Object.assign(Object.assign({}, this.body), { reserved })); } const hash = blake2b256(buf); if (delegateFor) { if (!/^0x[0-9a-f]{40}$/i.test(delegateFor)) { throw new Error('delegateFor expected address'); } return 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.recover(signingHash, this.signature.slice(0, 65)); return address.fromPublicKey(pubKey); } 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.recover(signingHash, this.signature.slice(65)); return address.fromPublicKey(pubKey); } catch (_a) { return null; } } /** returns whether delegated. see https://github.com/vechain/VIPs/blob/master/vips/VIP-191.md */ get delegated() { var _a, _b; // tslint:disable-next-line:no-bitwise return (((_b = ((_a = this.body.reserved) !== null && _a !== void 0 ? _a : {}).features) !== null && _b !== void 0 ? _b : 0) & Transaction.DELEGATED_MASK) === Transaction.DELEGATED_MASK; } /** returns intrinsic gas it takes */ get intrinsicGas() { return Transaction.intrinsicGas(this.body.clauses); } /** encode into Buffer */ encode() { this.checkType(); const reserved = this._encodeReserved(); if (this.type === Transaction.Type.DynamicFee) { const raw = this.signature ? dynamicFeeTxRLP.encode(Object.assign(Object.assign({}, this.body), { reserved, signature: this.signature })) : unsignedDynamicFeeTxRLP.encode(Object.assign(Object.assign({}, this.body), { reserved })); return Buffer.concat([Buffer.from([Transaction.Type.DynamicFee]), raw]); } return this.signature ? legacyTxRLP.encode(Object.assign(Object.assign({}, this.body), { reserved, signature: this.signature })) : unsignedLegacyTxRLP.encode(Object.assign(Object.assign({}, this.body), { reserved })); } _encodeReserved() { var _a, _b, _c; const reserved = (_a = this.body.reserved) !== null && _a !== void 0 ? _a : {}; const list = [featuresKind.data((_b = reserved.features) !== null && _b !== void 0 ? _b : 0, 'reserved.features').encode(), ...((_c = reserved.unused) !== null && _c !== void 0 ? _c : [])]; // 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; } checkType() { // allow type to be undefined to be compatible with older spec if (this.body.hasOwnProperty('type') && this.body.type !== undefined && this.body.type !== Transaction.Type.Legacy && this.body.type !== Transaction.Type.DynamicFee) { throw new Error('unsupported transaction type: ' + this.body.type); } } } Transaction.DELEGATED_MASK = 1; (function (Transaction) { let Type; (function (Type) { Type[Type["Legacy"] = 0] = "Legacy"; Type[Type["DynamicFee"] = 81] = "DynamicFee"; })(Type = Transaction.Type || (Transaction.Type = {})); /** * 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.substring(i, i + 2) === '00') { sum += zgas; } else { sum += nzgas; } } return sum; } })(Transaction || (Transaction = {})); const unsignedLegacyTxRLP = new RLP({ name: 'unsigned legacy tx', kind: [ { name: 'chainTag', kind: new RLP.NumericKind(1) }, { name: 'blockRef', kind: new RLP.CompactFixedBlobKind(8) }, { name: 'expiration', kind: new RLP.NumericKind(4) }, { name: 'clauses', kind: { item: [ { name: 'to', kind: new RLP.NullableFixedBlobKind(20) }, { name: 'value', kind: new RLP.NumericKind(32) }, { name: 'data', kind: new RLP.BlobKind() }, ], }, }, { name: 'gasPriceCoef', kind: new RLP.NumericKind(1) }, { name: 'gas', kind: new RLP.NumericKind(8) }, { name: 'dependsOn', kind: new RLP.NullableFixedBlobKind(32) }, { name: 'nonce', kind: new RLP.NumericKind(8) }, { name: 'reserved', kind: { item: new RLP.BufferKind() } }, ], }); const legacyTxRLP = new RLP({ name: 'legacy tx', kind: [...unsignedLegacyTxRLP.profile.kind, { name: 'signature', kind: new RLP.BufferKind() }], }); const unsignedDynamicFeeTxRLP = new RLP({ name: 'unsigned dynamic fee tx', kind: [ { name: 'chainTag', kind: new RLP.NumericKind(1) }, { name: 'blockRef', kind: new RLP.CompactFixedBlobKind(8) }, { name: 'expiration', kind: new RLP.NumericKind(4) }, { name: 'clauses', kind: { item: [ { name: 'to', kind: new RLP.NullableFixedBlobKind(20) }, { name: 'value', kind: new RLP.NumericKind(32) }, { name: 'data', kind: new RLP.BlobKind() }, ], }, }, { name: 'maxPriorityFeePerGas', kind: new RLP.NumericKind(32) }, { name: 'maxFeePerGas', kind: new RLP.NumericKind(32) }, { name: 'gas', kind: new RLP.NumericKind(8) }, { name: 'dependsOn', kind: new RLP.NullableFixedBlobKind(32) }, { name: 'nonce', kind: new RLP.NumericKind(8) }, { name: 'reserved', kind: { item: new RLP.BufferKind() } }, ], }); const dynamicFeeTxRLP = new RLP({ name: 'dynamic fee tx', kind: [ ...unsignedDynamicFeeTxRLP.profile.kind, { name: 'signature', kind: new RLP.BufferKind() }, ], }); const featuresKind = new RLP.NumericKind(4); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHJhbnNhY3Rpb24uanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvdHJhbnNhY3Rpb24udHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLE9BQU8sRUFBRSxNQUFNLFdBQVcsQ0FBQTtBQUNuQyxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0sV0FBVyxDQUFBO0FBQ3RDLE9BQU8sRUFBRSxHQUFHLEVBQUUsTUFBTSxPQUFPLENBQUE7QUFDM0IsT0FBTyxFQUFFLFNBQVMsRUFBRSxNQUFNLGFBQWEsQ0FBQTtBQUN2QyxPQUFPLEVBQUUsTUFBTSxFQUFFLE1BQU0sUUFBUSxDQUFBO0FBRS9CLHVFQUF1RTtBQUN2RSxNQUFNLE9BQU8sV0FBVztJQUdwQjs7O09BR0c7SUFDSSxNQUFNLENBQUMsTUFBTSxDQUFDLEdBQVcsRUFBRSxRQUFrQjtRQUNoRCxJQUFJLElBQXNCLENBQUE7UUFDMUIsSUFBSSxHQUFHLENBQUMsTUFBTSxHQUFHLENBQUMsSUFBSSxHQUFHLENBQUMsQ0FBQyxDQUFDLEdBQUcsSUFBSSxFQUFFLENBQUM7WUFDbEMsSUFBSSxHQUFHLFdBQVcsQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFBO1FBQ2xDLENBQUM7YUFBTSxDQUFDO1lBQ0osSUFBSSxHQUFHLENBQUMsTUFBTSxLQUFLLENBQUMsRUFBRSxDQUFDO2dCQUNuQixNQUFNLElBQUksS0FBSyxDQUFDLDZCQUE2QixDQUFDLENBQUE7WUFDbEQsQ0FBQztZQUNELElBQUksR0FBRyxDQUFDLENBQUMsQ0FBQyxLQUFLLFdBQVcsQ0FBQyxJQUFJLENBQUMsVUFBVSxFQUFFLENBQUM7Z0JBQ3pDLElBQUksR0FBRyxXQUFXLENBQUMsSUFBSSxDQUFDLFVBQVUsQ0FBQTtnQkFDbEMsaURBQWlEO2dCQUNqRCxHQUFHLEdBQUcsR0FBRyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQTtZQUN0QixDQUFDO2lCQUFNLENBQUM7Z0JBQ0osTUFBTSxJQUFJLEtBQUss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