incubed
Version:
Typescript-version of the incubed client
167 lines • 7.38 kB
JavaScript
;
/***********************************************************
* This file is part of the Slock.it IoT Layer. *
* The Slock.it IoT Layer contains: *
* - USN (Universal Sharing Network) *
* - INCUBED (Trustless INcentivized remote Node Network) *
************************************************************
* Copyright (C) 2016 - 2018 Slock.it GmbH *
* All Rights Reserved. *
************************************************************
* You may use, distribute and modify this code under the *
* terms of the license contract you have concluded with *
* Slock.it GmbH. *
* For information about liability, maintenance etc. also *
* refer to the contract concluded with Slock.it GmbH. *
************************************************************
* For more information, please refer to https://slock.it *
* For questions, please contact info@slock.it *
***********************************************************/
Object.defineProperty(exports, "__esModule", { value: true });
const ethUtil = require("ethereumjs-util");
const Tx = require("ethereumjs-tx");
const util_1 = require("../../util/util");
/** RLP-functions */
exports.rlp = ethUtil.rlp;
/** serialize the data */
exports.serialize = (val) => exports.rlp.encode(val);
/** returns the hash of the object */
exports.hash = (val) => Array.isArray(val) ? ethUtil.rlphash(val) : ethUtil.keccak(val);
// types ...
/** converts it to a Buffer with 256 bytes length */
exports.bytes256 = val => util_1.toBuffer(val, 256);
/** converts it to a Buffer with 32 bytes length */
exports.bytes32 = val => util_1.toBuffer(val, 32);
/** converts it to a Buffer with 8 bytes length */
exports.bytes8 = val => util_1.toBuffer(val, 8);
/** converts it to a Buffer */
exports.bytes = val => util_1.toBuffer(val);
/** converts it to a Buffer with 20 bytes length */
exports.address = val => util_1.toBuffer(val, 20);
/** converts it to a Buffer with a variable length. 0 = length 0*/
exports.uint = val => util_1.toBuffer(val, 0);
exports.uint64 = val => util_1.toBuffer(val, 8);
/** create a Buffer[] from RPC-Response */
exports.toBlockHeader = (block) => [
exports.bytes32(block.parentHash),
exports.bytes32(block.sha3Uncles),
exports.address(block.miner || block.coinbase),
exports.bytes32(block.stateRoot),
exports.bytes32(block.transactionsRoot),
exports.bytes32(block.receiptsRoot || block.receiptRoot),
exports.bytes256(block.logsBloom),
exports.uint(block.difficulty),
exports.uint(block.number),
exports.uint(block.gasLimit),
exports.uint(block.gasUsed),
exports.uint(block.timestamp),
exports.bytes(block.extraData),
...block.sealFields
? block.sealFields.map(s => exports.rlp.decode(exports.bytes(s)))
: [
exports.bytes32(block.mixHash),
exports.bytes8(block.nonce)
]
];
/** create a Buffer[] from RPC-Response */
exports.toTransaction = (tx) => [
exports.uint(tx.nonce),
exports.uint(tx.gasPrice),
exports.uint(tx.gas || tx.gasLimit),
tx.to ? exports.address(tx.to) : Buffer.alloc(0),
exports.uint(tx.value),
exports.bytes(tx.input || tx.data),
exports.uint(tx.v),
exports.uint(tx.r),
exports.uint(tx.s)
];
// encode the account
exports.toAccount = (account) => [
exports.uint(account.nonce),
exports.uint(account.balance),
exports.bytes32(account.storageHash || ethUtil.KECCAK256_RLP),
exports.bytes32(account.codeHash || ethUtil.KECCAK256_NULL)
];
/** create a Buffer[] from RPC-Response */
exports.toReceipt = (r) => [
exports.uint(r.status || r.root),
exports.uint(r.cumulativeGasUsed),
exports.bytes256(r.logsBloom),
r.logs.map(l => [
exports.address(l.address),
l.topics.map(exports.bytes32),
exports.bytes(l.data)
])
].slice(r.status === null && r.root === null ? 1 : 0);
/**
* encodes and decodes the blockheader
*/
class Block {
get parentHash() { return this.raw[0]; }
get uncleHash() { return this.raw[1]; }
get coinbase() { return this.raw[2]; }
get stateRoot() { return this.raw[3]; }
get transactionsTrie() { return this.raw[4]; }
get receiptTrie() { return this.raw[5]; }
get bloom() { return this.raw[6]; }
get difficulty() { return this.raw[7]; }
get number() { return this.raw[8]; }
get gasLimit() { return this.raw[9]; }
get gasUsed() { return this.raw[10]; }
get timestamp() { return this.raw[11]; }
get extra() { return this.raw[12]; }
get sealedFields() { return this.raw.slice(13); }
/** creates a Block-Onject from either the block-data as returned from rpc, a buffer or a hex-string of the encoded blockheader */
constructor(data) {
if (Buffer.isBuffer(data))
this.raw = ethUtil.rlp.decode(data);
else if (typeof data === 'string')
this.raw = ethUtil.rlp.decode(Buffer.from(data.replace('0x', ''), 'hex'));
else if (typeof data === 'object') {
this.raw = exports.toBlockHeader(data);
if (data.transactions && typeof data.transactions[0] === 'object')
this.transactions = data.transactions.map(createTx);
}
}
/** the blockhash as buffer */
hash() {
return exports.hash(this.raw);
}
/** the blockhash as buffer without the seal fields*/
bareHash() {
return exports.hash(this.raw.slice(0, 13));
}
/** the serialized header as buffer */
serializeHeader() {
return exports.serialize(this.raw);
}
}
exports.Block = Block;
/** creates a Transaction-object from the rpc-transaction-data */
function createTx(transaction) {
const txParams = Object.assign({}, transaction, { nonce: util_1.toHex(transaction.nonce) || '0x00', gasPrice: util_1.toHex(transaction.gasPrice) || '0x00', value: util_1.toHex(transaction.value || 0), gasLimit: util_1.toHex(transaction.gasLimit === undefined ? transaction.gas : transaction.gasLimit), data: util_1.toHex(transaction.gasLimit === undefined ? transaction.input : transaction.data), to: transaction.to ? ethUtil.setLengthLeft(ethUtil.toBuffer(transaction.to), 20) : null, v: transaction.v < 27 ? transaction.v + 27 : transaction.v });
const fromAddress = ethUtil.toBuffer(txParams.from);
delete txParams.from;
const tx = new Tx(txParams);
tx._from = fromAddress;
tx.getSenderAddress = function () { return fromAddress; };
if (txParams.hash && txParams.hash !== '0x' + ethUtil.keccak(tx.serialize()).toString('hex'))
throw new Error('wrong txhash! : ' + (txParams.hash + '!== 0x' + ethUtil.keccak(tx.serialize()).toString('hex')) + ' full tx=' + tx.serialize().toString('hex'));
// override hash
const txHash = ethUtil.toBuffer(txParams.hash);
if (txParams.hash)
tx.hash = function () { return txHash; };
return tx;
}
exports.createTx = createTx;
/** converts blockdata to a hexstring*/
function blockToHex(block) {
return util_1.toHex(new Block(block).serializeHeader());
}
exports.blockToHex = blockToHex;
/** converts a hexstring to a block-object */
function blockFromHex(hex) {
return new Block(hex);
}
exports.blockFromHex = blockFromHex;
//# sourceMappingURL=serialize.js.map