-
Notifications
You must be signed in to change notification settings - Fork 846
Block library refactoring #883
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 5 commits
c053761
ff46c55
dd228bc
608d804
17a33a8
72b5b78
8adcdf9
8987003
5f5e9f2
5351fb8
ce1dac1
526f986
75689e6
8923f71
6a2c193
381f5e1
7eecf80
395c6f8
be5c8d2
7fa486d
91d45d7
7e788c3
bc459e8
ea8a401
b694010
1f66378
9f9bab0
7ce9132
a5d3d14
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,7 +1,7 @@ | ||
| import { BaseTrie as Trie } from 'merkle-patricia-tree' | ||
| import { BN, rlp, keccak256, KECCAK256_RLP, baToJSON } from 'ethereumjs-util' | ||
| import Common from '@ethereumjs/common' | ||
| import { Transaction } from '@ethereumjs/tx' | ||
| import { Transaction, TxOptions } from '@ethereumjs/tx' | ||
| import { BlockHeader } from './header' | ||
| import { Blockchain, BlockData, BlockOptions } from './types' | ||
|
|
||
|
|
@@ -16,6 +16,73 @@ export class Block { | |
|
|
||
| private readonly _common: Common | ||
|
|
||
| public static fromBlockData(blockData: BlockData, opts: BlockOptions = {}) { | ||
| // Checking at runtime, to prevent errors down the path for JavaScript consumers. | ||
| if (blockData === null) { | ||
| blockData = {} | ||
| } | ||
|
|
||
| const headerData = blockData.header || {} | ||
| const txsData = blockData.transactions || [] | ||
| const uncleHeadersData = blockData.uncleHeaders || [] | ||
|
|
||
| const header = BlockHeader.fromHeaderData(headerData, opts) | ||
|
|
||
| // parse transactions | ||
| let transactions = [] | ||
| for (const txData of txsData) { | ||
| transactions.push(Transaction.fromTxData(txData, opts as TxOptions)) | ||
| } | ||
|
|
||
| // parse uncle headers | ||
| let uncleHeaders = [] | ||
| for (const uncleHeaderData of uncleHeadersData) { | ||
| uncleHeaders.push(BlockHeader.fromHeaderData(uncleHeaderData, opts)) | ||
| } | ||
|
|
||
| return new Block(header, transactions, uncleHeaders, opts) | ||
| } | ||
|
|
||
| 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[][]] | ||
| 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 = {}, | ||
| ) { | ||
| if (values.length > 3) { | ||
| throw new Error('invalid block. More values than expected were received') | ||
| } | ||
|
|
||
| const headerArray = values[0] || [] | ||
| const txsData = values[1] || [] | ||
| const uncleHeadersData = values[2] || [] | ||
|
|
||
| const header = BlockHeader.fromValuesArray(headerArray, opts) | ||
|
|
||
| // parse transactions | ||
| let transactions = [] | ||
| for (const txData of txsData) { | ||
| transactions.push(Transaction.fromValuesArray(txData as Buffer[], opts as TxOptions)) | ||
| } | ||
|
|
||
| // parse uncle headers | ||
| let uncleHeaders = [] | ||
| for (const uncleHeaderData of uncleHeadersData) { | ||
| uncleHeaders.push(BlockHeader.fromValuesArray(uncleHeaderData as Buffer[], opts)) | ||
| } | ||
|
|
||
| return new Block(header, transactions, uncleHeaders, opts) | ||
| } | ||
|
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ah, thought we can really keep this as simple as you proposed (or more or less), so optimally
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah I wanted to too but in practice (in our test suite) it was helpful to accept custom overrides as well. |
||
|
|
||
| /** | ||
| * Creates a new block object | ||
| * | ||
|
|
@@ -27,50 +94,16 @@ export class Block { | |
| * @param options - The options for this block (like the chain setup) | ||
| */ | ||
| constructor( | ||
| data: Buffer | [Buffer[], Buffer[], Buffer[]] | BlockData = {}, | ||
| options: BlockOptions = {}, | ||
| header: BlockHeader, | ||
| transactions: Transaction[], | ||
| uncleHeaders: BlockHeader[], | ||
| //data: Buffer | [Buffer[], Buffer[], Buffer[]] | BlockData = {}, | ||
| opts: BlockOptions = {}, | ||
| ) { | ||
| // Checking at runtime, to prevent errors down the path for JavaScript consumers. | ||
| if (data === null) { | ||
| data = {} | ||
| } | ||
|
|
||
| let rawTransactions | ||
| let rawUncleHeaders | ||
|
|
||
| if (Buffer.isBuffer(data)) { | ||
| // We do this to silence a TS error. We know that after this statement, data is | ||
| // a [Buffer[], Buffer[], Buffer[]] | ||
| const dataAsAny = rlp.decode(data) as any | ||
| data = dataAsAny as [Buffer[], Buffer[], Buffer[]] | ||
| } | ||
|
|
||
| // Initialize the block header | ||
| if (Array.isArray(data)) { | ||
| this.header = new BlockHeader(data[0], options) | ||
| rawTransactions = data[1] | ||
| rawUncleHeaders = data[2] | ||
| } else { | ||
| this.header = new BlockHeader(data.header, options) | ||
| rawTransactions = data.transactions || [] | ||
| rawUncleHeaders = data.uncleHeaders || [] | ||
| } | ||
| this.header = header | ||
| this.transactions = transactions | ||
| this.uncleHeaders = uncleHeaders | ||
| this._common = this.header._common | ||
|
|
||
| // parse uncle headers | ||
| for (let i = 0; i < rawUncleHeaders.length; i++) { | ||
| this.uncleHeaders.push(new BlockHeader(rawUncleHeaders[i], options)) | ||
| } | ||
|
|
||
| // parse transactions | ||
| const txOpts = { common: this._common } | ||
| for (let i = 0; i < rawTransactions.length; i++) { | ||
| const txData = rawTransactions[i] | ||
| const tx = Array.isArray(txData) | ||
| ? Transaction.fromValuesArray(txData as Buffer[], txOpts) | ||
| : Transaction.fromRlpSerializedTx(txData as Buffer, txOpts) | ||
| this.transactions.push(tx) | ||
| } | ||
| } | ||
|
|
||
| get raw(): [Buffer[], Buffer[], Buffer[]] { | ||
|
|
@@ -103,9 +136,9 @@ export class Block { | |
| serialize(rlpEncode: false): [Buffer[], Buffer[], Buffer[]] | ||
| serialize(rlpEncode = true) { | ||
| const raw = [ | ||
| this.header.raw, | ||
| this.header.raw(), | ||
| this.transactions.map((tx) => tx.serialize()), | ||
| this.uncleHeaders.map((uh) => uh.raw), | ||
| this.uncleHeaders.map((uh) => uh.raw()), | ||
| ] | ||
|
|
||
| return rlpEncode ? rlp.encode(raw) : raw | ||
|
|
@@ -184,7 +217,7 @@ export class Block { | |
| * Validates the uncle's hash | ||
| */ | ||
| validateUnclesHash(): boolean { | ||
| const raw = rlp.encode(this.uncleHeaders.map((uh) => uh.raw)) | ||
| const raw = rlp.encode(this.uncleHeaders.map((uh) => uh.raw())) | ||
|
|
||
| return keccak256(raw).equals(this.header.uncleHash) | ||
| } | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.