Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
c053761
block -> refactor: reworked header class with static factory instanti…
holgerd77 Sep 21, 2020
ff46c55
block -> refactoring: added new static factory helpers to block class
holgerd77 Sep 21, 2020
dd228bc
block -> refactor: fix build errors, remove unused imports, unpad num…
jochem-brouwer Sep 24, 2020
608d804
block -> rename Header to BlockHeader
jochem-brouwer Sep 28, 2020
17a33a8
block/tx -> fix block tests
jochem-brouwer Sep 28, 2020
72b5b78
block -> enforce BNs on fields which are interpreted as numbers
jochem-brouwer Sep 28, 2020
8adcdf9
block -> edge case in toBN
jochem-brouwer Sep 29, 2020
8987003
ethash -> make ethash compatible with block
jochem-brouwer Sep 29, 2020
5f5e9f2
Merge branch 'master' into refactor-block-library
ryanio Oct 7, 2020
5351fb8
have validateTransactions return a string[] (https://github.com/ether…
ryanio Oct 7, 2020
ce1dac1
let => const
ryanio Oct 7, 2020
526f986
set default param to resolve js runtime check
ryanio Oct 7, 2020
75689e6
continue refactoring and simplifying methods
ryanio Oct 8, 2020
8923f71
api updates
ryanio Oct 8, 2020
6a2c193
continuing work
ryanio Oct 8, 2020
381f5e1
inline buffer validations. add checks for extraData, mixHash and nonce
ryanio Oct 8, 2020
7eecf80
various fixups
ryanio Oct 8, 2020
395c6f8
continuing various work
ryanio Oct 9, 2020
be5c8d2
continuing work and refactoring
ryanio Oct 9, 2020
7fa486d
Merge branch 'master' into refactor-block-library
ryanio Oct 9, 2020
91d45d7
re-add timestamp to genesis (for rinkeby)
ryanio Oct 9, 2020
7e788c3
last fixups
ryanio Oct 9, 2020
bc459e8
update readme, benchmarks
ryanio Oct 9, 2020
ea8a401
update vm readme, simplify validate
ryanio Oct 10, 2020
b694010
fix timestamp validation
ryanio Oct 10, 2020
1f66378
use native eq
ryanio Oct 10, 2020
9f9bab0
make blockchain optional in block.validate()
ryanio Oct 10, 2020
7ce9132
fixups
ryanio Oct 10, 2020
a5d3d14
remove BLOCK_difficulty_GivenAsList from skip list (https://github.co…
ryanio Oct 12, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 8 additions & 6 deletions packages/block/src/block.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,17 +45,19 @@ export class Block {

public static fromRLPSerializedBlock(serialized: Buffer, opts: BlockOptions = {}) {
// We do this to silence a TS error. We know that after this statement, data is
// a [Buffer[], Buffer[], Buffer[]]
let values = (rlp.decode(serialized) as any) as [Buffer[], Buffer[], Buffer[]]

// a [Buffer[], Buffer[][], Buffer[][]]
let values = (rlp.decode(serialized) as any) as [Buffer[], Buffer[][], Buffer[][]]
if (!Array.isArray(values)) {
throw new Error('Invalid serialized block input. Must be array')
}

return Block.fromValuesArray(values, opts)
}

public static fromValuesArray(values: [Buffer[], Buffer[], Buffer[]], opts: BlockOptions = {}) {
public static fromValuesArray(
values: [Buffer[], Buffer[][], Buffer[][]],
opts: BlockOptions = {},
) {
if (values.length > 3) {
throw new Error('invalid block. More values than expected were received')
}
Expand All @@ -69,13 +71,13 @@ export class Block {
// parse transactions
let transactions = []
for (const txData of txsData) {
transactions.push(Transaction.fromRlpSerializedTx(txData, opts as TxOptions))
transactions.push(Transaction.fromValuesArray(txData as Buffer[], opts as TxOptions))
}

// parse uncle headers
let uncleHeaders = []
for (const uncleHeaderData of uncleHeadersData) {
uncleHeaders.push(BlockHeader.fromRLPSerializedHeader(uncleHeaderData, opts))
uncleHeaders.push(BlockHeader.fromValuesArray(uncleHeaderData as Buffer[], opts))
}

return new Block(header, transactions, uncleHeaders, opts)
Expand Down
8 changes: 4 additions & 4 deletions packages/block/src/header-from-rpc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,10 @@ export default function blockHeaderFromRpc(blockParams: any, options?: BlockOpti
options,
)

// override hash in case something was missing
blockHeader.hash = function () {
return toBuffer(blockParams.hash)
}
// override hash in case something was missing TODO: why do we need this?
//blockHeader.hash = function () {
// return toBuffer(blockParams.hash)
//}

return blockHeader
}
14 changes: 7 additions & 7 deletions packages/block/src/header.ts
Original file line number Diff line number Diff line change
Expand Up @@ -189,12 +189,12 @@ export class BlockHeader {
'Genesis parameters can only be set with a Common instance set to chainstart',
)
}
this.timestamp = this._common.genesis().timestamp
this.gasLimit = this._common.genesis().gasLimit
this.difficulty = this._common.genesis().difficulty
this.extraData = this._common.genesis().extraData
this.nonce = this._common.genesis().nonce
this.stateRoot = this._common.genesis().stateRoot
this.timestamp = toBuffer(this._common.genesis().timestamp || this.timestamp)
this.gasLimit = toBuffer(this._common.genesis().gasLimit || this.gasLimit)
this.difficulty = toBuffer(this._common.genesis().difficulty || this.difficulty)
this.extraData = toBuffer(this._common.genesis().extraData || this.extraData)
this.nonce = toBuffer(this._common.genesis().nonce || this.nonce)
this.stateRoot = toBuffer(this._common.genesis().stateRoot || this.stateRoot)
this.number = toBuffer(0)
}

Expand Down Expand Up @@ -414,7 +414,7 @@ export class BlockHeader {
* Checks if the block header is a genesis header.
*/
isGenesis(): boolean {
return this.number.equals(toBuffer(0))
return this.number.equals(zeros(0))
}

/**
Expand Down
39 changes: 20 additions & 19 deletions packages/block/test/block.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,14 @@ import { Block } from '../src/block'
tape('[Block]: block functions', function (t) {
t.test('should test block initialization', function (st) {
const common = new Common({ chain: 'ropsten', hardfork: 'chainstart' })
const block1 = new Block(undefined, { common: common, initWithGenesisHeader: true })
const block1 = Block.fromBlockData({}, { common: common, initWithGenesisHeader: true })
st.ok(block1.hash().toString('hex'), 'block should initialize')
st.end()
})

t.test('should initialize with undefined parameters without throwing', function (st) {
st.doesNotThrow(function () {
new Block()
Block.fromBlockData({})
st.end()
})
})
Expand All @@ -22,7 +22,7 @@ tape('[Block]: block functions', function (t) {
st.doesNotThrow(function () {
const common = new Common({ chain: 'ropsten' })
const opts = { common }
new Block(undefined, opts)
Block.fromBlockData({}, opts)
st.end()
})
})
Expand All @@ -39,44 +39,44 @@ tape('[Block]: block functions', function (t) {
}

t.test('should test transaction validation', async function (st) {
const block = new Block(rlp.decode(testData.blocks[0].rlp))
const block = Block.fromRLPSerializedBlock(testData.blocks[0].rlp)
st.plan(2)
await testTransactionValidation(st, block)
})

t.test('should test transaction validation with empty transaction list', async function (st) {
const block = new Block()
const block = Block.fromBlockData({})
st.plan(2)
await testTransactionValidation(st, block)
})

const testData2 = require('./testdata/testdata2.json')
t.test('should test uncles hash validation', function (st) {
const block = new Block(rlp.decode(testData2.blocks[2].rlp))
const block = Block.fromRLPSerializedBlock(testData2.blocks[2].rlp)
st.equal(block.validateUnclesHash(), true)
st.end()
})

t.test('should test isGenesis (mainnet default)', function (st) {
const block = new Block()
const block = Block.fromBlockData({ header: { number: Buffer.from('01', 'hex') } })
st.notEqual(block.isGenesis(), true)
block.header.number = Buffer.from([])
st.equal(block.isGenesis(), true)
const genesisBlock = Block.fromBlockData({ header: { number: Buffer.from([]) } })
st.equal(genesisBlock.isGenesis(), true)
st.end()
})

t.test('should test isGenesis (ropsten)', function (st) {
const common = new Common({ chain: 'ropsten' })
const block = new Block(undefined, { common })
const block = Block.fromBlockData({ header: { number: Buffer.from('01', 'hex') } }, { common })
st.notEqual(block.isGenesis(), true)
block.header.number = Buffer.from([])
st.equal(block.isGenesis(), true)
const genesisBlock = Block.fromBlockData({ header: { number: Buffer.from([]) } }, { common })
st.equal(genesisBlock.isGenesis(), true)
st.end()
})

const testDataGenesis = require('./testdata/genesishashestest.json').test
t.test('should test genesis hashes (mainnet default)', function (st) {
const genesisBlock = new Block(undefined, { initWithGenesisHeader: true })
const genesisBlock = Block.fromBlockData({}, { initWithGenesisHeader: true })
const rlp = genesisBlock.serialize()
st.strictEqual(rlp.toString('hex'), testDataGenesis.genesis_rlp_hex, 'rlp hex match')
st.strictEqual(
Expand All @@ -89,7 +89,7 @@ tape('[Block]: block functions', function (t) {

t.test('should test genesis hashes (ropsten)', function (st) {
const common = new Common({ chain: 'ropsten', hardfork: 'chainstart' })
const genesisBlock = new Block(undefined, { common: common, initWithGenesisHeader: true })
const genesisBlock = Block.fromBlockData({}, { common: common, initWithGenesisHeader: true })
st.strictEqual(
genesisBlock.hash().toString('hex'),
common.genesis().hash.slice(2),
Expand All @@ -100,7 +100,7 @@ tape('[Block]: block functions', function (t) {

t.test('should test genesis hashes (rinkeby)', function (st) {
const common = new Common({ chain: 'rinkeby', hardfork: 'chainstart' })
const genesisBlock = new Block(undefined, { common: common, initWithGenesisHeader: true })
const genesisBlock = Block.fromBlockData({}, { common: common, initWithGenesisHeader: true })
st.strictEqual(
genesisBlock.hash().toString('hex'),
common.genesis().hash.slice(2),
Expand All @@ -111,7 +111,7 @@ tape('[Block]: block functions', function (t) {

t.test('should test genesis parameters (ropsten)', function (st) {
const common = new Common({ chain: 'ropsten', hardfork: 'chainstart' })
const genesisBlock = new Block(undefined, { common, initWithGenesisHeader: true })
const genesisBlock = Block.fromBlockData({}, { common, initWithGenesisHeader: true })
const ropstenStateRoot = '217b0bbcfb72e2d57e28f33cb361b9983513177755dc3f33ce3e7022ed62b77b'
st.strictEqual(
genesisBlock.header.stateRoot.toString('hex'),
Expand All @@ -122,7 +122,7 @@ tape('[Block]: block functions', function (t) {
})

t.test('should test toJSON', function (st) {
const block = new Block(rlp.decode(testData2.blocks[2].rlp))
const block = Block.fromRLPSerializedBlock(testData2.blocks[2].rlp)
st.equal(typeof block.toJSON(), 'object')
st.equal(typeof block.toJSON(true), 'object')
st.end()
Expand All @@ -136,16 +136,17 @@ tape('[Block]: block functions', function (t) {
const common = new Common({ chain: 'mainnet', hardfork: 'dao' })
st.throws(
function () {
new Block(blockData, { common: common })
Block.fromValuesArray(blockData, { common: common })
},
/Error: extraData should be 'dao-hard-fork'$/,
'should throw on DAO HF block with wrong extra data',
) // eslint-disable-line

// Set extraData to dao-hard-fork
blockData[0][12] = Buffer.from('64616f2d686172642d666f726b', 'hex')

st.doesNotThrow(function () {
new Block(blockData, { common: common })
Block.fromValuesArray(blockData, { common: common })
}, 'should not throw on DAO HF block with correct extra data')
st.end()
})
Expand Down
33 changes: 23 additions & 10 deletions packages/block/test/difficulty.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import * as tape from 'tape'
import { toBuffer, bufferToInt, intToBuffer } from 'ethereumjs-util'
import { Block } from '../src/block'
import Common from '@ethereumjs/common'
import blockFromRpc from '../src/from-rpc'

const { BN } = require('ethereumjs-util')

Expand Down Expand Up @@ -42,15 +43,27 @@ tape('[Header]: difficulty tests', (t) => {
for (const testName in testData) {
const test = testData[testName]
const common = new Common({ chain: 'mainnet', hardfork: hardfork })
const parentBlock = new Block(undefined, { common })
parentBlock.header.timestamp = test.parentTimestamp
parentBlock.header.difficulty = test.parentDifficulty
parentBlock.header.uncleHash = test.parentUncles
const parentBlock = Block.fromBlockData(
{
header: {
timestamp: test.parentTimestamp,
difficulty: test.parentDifficulty,
uncleHash: test.parentUncles,
},
},
{ common },
)

const block = new Block(undefined, { common })
block.header.timestamp = test.currentTimestamp
block.header.difficulty = test.currentDifficulty
block.header.number = test.currentBlockNumber
const block = Block.fromBlockData(
{
header: {
timestamp: test.currentTimestamp,
difficulty: test.currentDifficulty,
number: test.currentBlockNumber,
},
},
{ common },
)

runDifficultyTests(
test,
Expand Down Expand Up @@ -78,7 +91,7 @@ tape('[Header]: difficulty tests', (t) => {
uncleHash: test.parentUncles,
},
}
const parentBlock = new Block(parentData, { common, hardforkByBlockNumber: true })
const parentBlock = Block.fromBlockData(parentData, { common, hardforkByBlockNumber: true })

const blockData = {
header: {
Expand All @@ -87,7 +100,7 @@ tape('[Header]: difficulty tests', (t) => {
number: test.currentBlockNumber,
},
}
const block = new Block(blockData, { common, hardforkByBlockNumber: true })
const block = Block.fromBlockData(blockData, { common, hardforkByBlockNumber: true })

runDifficultyTests(
test,
Expand Down
7 changes: 4 additions & 3 deletions packages/block/test/header.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,12 @@ import * as tape from 'tape'
import Common from '@ethereumjs/common'
import { rlp, toBuffer, zeros, KECCAK256_RLP, KECCAK256_RLP_ARRAY } from 'ethereumjs-util'
import { BlockHeader } from '../src/header'
import { Block } from '../src'
//import { Block } from '../src/block'

tape('[Block]: Header functions', function (t) {
t.test('should create with default constructor', function (st) {
function compareDefaultHeader(st: tape.Test, header: Header) {
function compareDefaultHeader(st: tape.Test, header: BlockHeader) {
st.deepEqual(header.parentHash, zeros(32))
st.ok(header.uncleHash.equals(KECCAK256_RLP_ARRAY))
st.deepEqual(header.coinbase, zeros(20))
Expand Down Expand Up @@ -55,7 +56,7 @@ tape('[Block]: Header functions', function (t) {
})*/

t.test('should test isGenesis', function (st) {
let header = BlockHeader.fromHeaderData({})
let header = BlockHeader.fromHeaderData({ number: Buffer.from('01', 'hex') })
st.equal(header.isGenesis(), false)
header = BlockHeader.fromHeaderData({}, { initWithGenesisHeader: true })
st.equal(header.isGenesis(), true)
Expand All @@ -76,7 +77,7 @@ tape('[Block]: Header functions', function (t) {
t.test('should test genesis parameters (ropsten)', function (st) {
const common = new Common({ chain: 'ropsten', hardfork: 'chainstart' })
const genesisHeader = BlockHeader.fromHeaderData({}, { common, initWithGenesisHeader: true })
const ropstenStateRoot = '0x217b0bbcfb72e2d57e28f33cb361b9983513177755dc3f33ce3e7022ed62b77b'
const ropstenStateRoot = '217b0bbcfb72e2d57e28f33cb361b9983513177755dc3f33ce3e7022ed62b77b'
st.strictEqual(
genesisHeader.stateRoot.toString('hex'),
ropstenStateRoot,
Expand Down
7 changes: 5 additions & 2 deletions packages/tx/src/transaction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,11 @@ export default class Transaction {
public readonly s?: BN

public static fromTxData(txData: TxData, opts?: TxOptions) {
const { nonce, gasLimit, gasPrice, to, value, data, v, r, s } = txData

const { nonce, gasLimit, gasPrice, value, data, v, r, s } = txData
let to = txData.to
if (to instanceof Address) {
to = to.buf
}
return new Transaction(
new BN(toBuffer(nonce || '0x')),
new BN(toBuffer(gasPrice || '0x')),
Expand Down