thor-devkit
Version:
Typescript library to aid DApp development on VeChain Thor
319 lines • 26.4 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.Transaction = void 0;
const address_1 = require("./address");
const blake2b_1 = require("./blake2b");
const rlp_1 = require("./rlp");
const secp256k1_1 = require("./secp256k1");
const buffer_1 = require("buffer");
/** Transaction class defines VeChainThor'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 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_1.secp256k1.recover(signingHash, this.signature.slice(0, 65));
const origin = address_1.address.fromPublicKey(pubKey);
return '0x' + (0, blake2b_1.blake2b256)(signingHash, buffer_1.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_1.Buffer.concat([buffer_1.Buffer.from([Transaction.Type.DynamicFee]), raw]);
}
else {
buf = unsignedLegacyTxRLP.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_1.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 address_1.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_1.secp256k1.recover(signingHash, this.signature.slice(65));
return address_1.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_1.Buffer.concat([buffer_1.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);
}
}
}
exports.Transaction = Transaction;
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 || (exports.Transaction = Transaction = {}));
const unsignedLegacyTxRLP = new rlp_1.RLP({
name: 'unsigned legacy 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: '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 legacyTxRLP = new rlp_1.RLP({
name: 'legacy tx',
kind: [...unsignedLegacyTxRLP.profile.kind, { name: 'signature', kind: new rlp_1.RLP.BufferKind() }],
});
const unsignedDynamicFeeTxRLP = new rlp_1.RLP({
name: 'unsigned dynamic fee 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: 'data', kind: new rlp_1.RLP.BlobKind() },
],
},
},
{ name: 'maxPriorityFeePerGas', kind: new rlp_1.RLP.NumericKind(32) },
{ name: 'maxFeePerGas', kind: new rlp_1.RLP.NumericKind(32) },
{ 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 dynamicFeeTxRLP = new rlp_1.RLP({
name: 'dynamic fee tx',
kind: [
...unsignedDynamicFeeTxRLP.profile.kind,
{ name: 'signature', kind: new rlp_1.RLP.BufferKind() },
],
});
const featuresKind = new rlp_1.RLP.NumericKind(4);
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHJhbnNhY3Rpb24uanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvdHJhbnNhY3Rpb24udHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBQUEsdUNBQW1DO0FBQ25DLHVDQUFzQztBQUN0QywrQkFBMkI7QUFDM0IsMkNBQXVDO0FBQ3ZDLG1DQUErQjtBQUUvQix1RUFBdUU7QUFDdkUsTUFBYSxXQUFXO0lBR3BCOzs7T0FHRztJQUNJLE1BQU0sQ0FBQyxNQUFNLENBQUMsR0FBVyxFQUFFLFFBQWtCO1FBQ2hELElBQUksSUFBc0IsQ0FBQTtRQUMxQixJQUFJLEdBQUcsQ0FBQyxNQUFNLEdBQUcsQ0FBQyxJQUFJLEdBQUcsQ0FBQyxDQUFDLENBQUMsR0FBRyxJQUFJLEVBQUUsQ0FBQztZQUNsQyxJQUFJLEdBQUcsV0FBVyxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUE7UUFDbEMsQ0FBQzthQUFNLENBQUM7WUFDSixJQUFJLEdBQUcsQ0FBQyxNQUFNLEtBQUssQ0FBQyxFQUFFLENBQUM7Z0JBQ25CLE1BQU0sSUFBSSxLQUFLLENBQUMsNkJBQTZCLENBQUMsQ0FBQTtZQUNsRCxDQUFDO1lBQ0QsSUFBSSxHQUFHLENBQUMsQ0FBQyxDQUFDLEtBQUssV0FBVyxDQUFDLElBQUksQ0FBQyxVQUFVLEVBQUUsQ0FBQztnQkFDekMsSUFBSSxHQUFHLFdBQVcsQ0FBQyxJQUFJLENBQUMsVUFBVSxDQUFBO2dCQUNsQyxpREFBaUQ7Z0JBQ2pELEdBQUcsR0FBRyxHQUFHLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFBO1lBQ3RCLENBQUM7aUJBQU0sQ0FBQztnQkFDSixNQUFNLElBQUksS0FBSyxDQUFDLGtDQUFrQyxHQUFHLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFBO1lBQ2hFLENBQUM7UUFDTCxDQUFDO1FBRUQsSUFBSSxJQUF5RCxDQUFBO1FBQzdELElBQUksU0FBNkIsQ0FBQTtRQUNqQyxJQUFJLFFBQVEsRUFBRSxDQUFDO1lBQ1gs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