Skip to content

Commit

Permalink
Merge pull request #812 from ethereumjs/tx-refactor
Browse files Browse the repository at this point in the history
Refactor tx lib
  • Loading branch information
holgerd77 authored Sep 21, 2020
2 parents d15e7be + 4491218 commit b1429b9
Show file tree
Hide file tree
Showing 48 changed files with 2,448 additions and 1,080 deletions.
2 changes: 1 addition & 1 deletion packages/account/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
},
"homepage": "https://github.com/ethereumjs/ethereumjs-vm/tree/master/packages/account#synopsis",
"dependencies": {
"ethereumjs-util": "^7.0.4",
"ethereumjs-util": "^7.0.5",
"rlp": "^2.2.3",
"safe-buffer": "^5.1.1"
},
Expand Down
9 changes: 2 additions & 7 deletions packages/account/test/index.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -98,13 +98,8 @@ tape('serialize', function (tester) {
codeHash: '0xc5d2461236f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470',
}
const account = new Account(raw)
t.equals(
Buffer.compare(
account.serialize(),
rlp.encode([raw.nonce, raw.balance, raw.stateRoot, raw.codeHash]),
),
0,
)
const accountRlp = rlp.encode([raw.nonce, raw.balance, raw.stateRoot, raw.codeHash])
t.ok(account.serialize().equals(accountRlp))
t.end()
})
})
Expand Down
2 changes: 1 addition & 1 deletion packages/block/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@
"@ethereumjs/common": "^1.5.1",
"@ethereumjs/tx": "^2.1.2",
"@types/bn.js": "^4.11.6",
"ethereumjs-util": "^7.0.4",
"ethereumjs-util": "^7.0.5",
"merkle-patricia-tree": "^4.0.0"
},
"devDependencies": {
Expand Down
25 changes: 12 additions & 13 deletions packages/block/src/block.ts
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 { BN, rlp, keccak256, KECCAK256_RLP, baToJSON, bufferToInt } from 'ethereumjs-util'
import { Transaction, TransactionOptions } from '@ethereumjs/tx'
import { Transaction } from '@ethereumjs/tx'
import { BlockHeader } from './header'
import { Blockchain, BlockData, BlockOptions } from './types'

Expand Down Expand Up @@ -64,7 +64,10 @@ export class Block {

// parse transactions
for (let i = 0; i < rawTransactions.length; i++) {
const tx = new Transaction(rawTransactions[i], { common: this._common })
const txData = rawTransactions[i]
const tx = Array.isArray(txData)
? Transaction.fromValuesArray(txData as Buffer[], this._common)
: Transaction.fromRlpSerializedTx(txData as Buffer, this._common)
this.transactions.push(tx)
}
}
Expand Down Expand Up @@ -100,7 +103,7 @@ export class Block {
serialize(rlpEncode = true) {
const raw = [
this.header.raw,
this.transactions.map((tx) => tx.raw),
this.transactions.map((tx) => tx.serialize()),
this.uncleHeaders.map((uh) => uh.raw),
]

Expand Down Expand Up @@ -141,17 +144,13 @@ export class Block {
const errors: string[] = []

this.transactions.forEach(function (tx, i) {
const error = tx.validate(true)
if (error) {
errors.push(`${error} at tx ${i}`)
const errs = tx.validate(true)
if (errs.length !== 0) {
errors.push(`errors at tx ${i}: ${errs.join(', ')}`)
}
})

if (!stringError) {
return errors.length === 0
}

return errors.join(' ')
return stringError ? errors.join(' ') : errors.length === 0
}

/**
Expand Down Expand Up @@ -223,7 +222,7 @@ export class Block {
if (labeled) {
return {
header: this.header.toJSON(true),
transactions: this.transactions.map((tx) => tx.toJSON(true)),
transactions: this.transactions.map((tx) => tx.toJSON()),
uncleHeaders: this.uncleHeaders.forEach((uh) => uh.toJSON(true)),
}
} else {
Expand Down
26 changes: 15 additions & 11 deletions packages/block/src/from-rpc.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { FakeTransaction, TransactionOptions } from '@ethereumjs/tx'
import { toBuffer, setLengthLeft } from 'ethereumjs-util'
import { Transaction, TxData } from '@ethereumjs/tx'
import { toBuffer, setLengthLeft, Address } from 'ethereumjs-util'
import { Block, BlockOptions } from './index'

import blockHeaderFromRpc from './header-from-rpc'
Expand Down Expand Up @@ -28,32 +28,36 @@ export default function blockFromRpc(blockParams: any, uncles?: any[], options?:
if (blockParams.transactions) {
for (const _txParams of blockParams.transactions) {
const txParams = normalizeTxParams(_txParams)

// override from address
const fromAddress = toBuffer(txParams.from)
const fromAddress = txParams.from ? Address.fromString(txParams.from) : Address.zero()
delete txParams.from

const tx = new FakeTransaction(txParams, options as TransactionOptions)
tx.from = fromAddress
tx.getSenderAddress = function () {
const tx = Transaction.fromTxData(txParams as TxData, (<any>block)._common)
const fakeTx = Object.create(tx)

// override getSenderAddress
fakeTx.getSenderAddress = () => {
return fromAddress
}
// override hash
const txHash = toBuffer(txParams.hash)
tx.hash = function () {
return txHash
fakeTx.hash = () => {
return toBuffer(txParams.hash)
}

block.transactions.push(tx)
block.transactions.push(fakeTx)
}
}

return block
}

function normalizeTxParams(_txParams: any) {
const txParams = Object.assign({}, _txParams)
// hot fix for https://github.com/ethereumjs/ethereumjs-util/issues/40

txParams.gasLimit = txParams.gasLimit === undefined ? txParams.gas : txParams.gasLimit
txParams.data = txParams.data === undefined ? txParams.input : txParams.data

// strict byte length checking
txParams.to = txParams.to ? setLengthLeft(toBuffer(txParams.to), 20) : null

Expand Down
3 changes: 1 addition & 2 deletions packages/block/test/block.spec.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import * as tape from 'tape'
import Common from '@ethereumjs/common'
import tape = require('tape')
import { rlp } from 'ethereumjs-util'

import { Block } from '../src/block'

tape('[Block]: block functions', function (t) {
Expand Down
2 changes: 1 addition & 1 deletion packages/block/test/difficulty.spec.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import * as tape from 'tape'
import { toBuffer, bufferToInt, intToBuffer } from 'ethereumjs-util'
import { Block } from '../src/block'
import tape = require('tape')
import Common from '@ethereumjs/common'

const { BN } = require('ethereumjs-util')
Expand Down
5 changes: 3 additions & 2 deletions packages/block/test/from-rpc.spec.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import tape = require('tape')
import * as tape from 'tape'
import blockFromRpc from '../src/from-rpc'
import blockHeaderFromRpc from '../src/header-from-rpc'
import * as blockData from './testdata/testdata-from-rpc.json'
Expand All @@ -15,7 +15,8 @@ tape('[fromRPC]: block #2924874', function (t) {

t.test('should create a block header with the correct hash', function (st) {
const block = blockHeaderFromRpc(blockData)
st.ok(block.hash().compare(Buffer.from(blockData.hash)))
const hash = Buffer.from(blockData.hash.slice(2), 'hex')
st.ok(block.hash().equals(hash))
st.end()
})

Expand Down
2 changes: 1 addition & 1 deletion packages/block/test/header.spec.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import tape = require('tape')
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'
Expand Down
2 changes: 1 addition & 1 deletion packages/blockchain/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@
"@ethereumjs/block": "^3.0.0",
"@ethereumjs/common": "^1.5.1",
"@ethereumjs/ethash": "^1.0.0",
"ethereumjs-util": "^7.0.4",
"ethereumjs-util": "^7.0.5",
"level-mem": "^5.0.1",
"lru-cache": "^5.1.1",
"rlp": "^2.2.3",
Expand Down
4 changes: 3 additions & 1 deletion packages/blockchain/test/util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,9 @@ export const isConsecutive = (blocks: Block[]) => {
if (index === 0) {
return false
}
return Buffer.compare(block.header.parentHash, blocks[index - 1].hash()) !== 0
const { parentHash } = block.header
const lastBlockHash = blocks[index - 1].hash()
return !parentHash.equals(lastBlockHash)
})
}

Expand Down
21 changes: 21 additions & 0 deletions packages/common/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,27 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
(modification: no type change headlines) and this project adheres to
[Semantic Versioning](http://semver.org/spec/v2.0.0.html).

## [2.0.0] - [UNRELEASED]

### New constructor

The constructor has been changed to accept a dict, PR [#863](https://github.com/ethereumjs/ethereumjs-vm/pull/863)

Example:

```typescript
import Common from '@ethereumjs/common'
const common = new Common({ chain: 'mainnet', hardfork: 'muirGlacier' })
```

### Hardfork by block number

A new function `setHardforkByBlockNumber()` has been added, PR [#863](https://github.com/ethereumjs/ethereumjs-vm/pull/863)

### Default hardfork

The default hardfork has been added as an accessible readonly property `DEFAULT_HARDFORK`, PR [#863](https://github.com/ethereumjs/ethereumjs-vm/pull/863)

## [1.5.1] - 2020-05-04

This is a maintenance release.
Expand Down
2 changes: 1 addition & 1 deletion packages/ethash/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
"dependencies": {
"@types/levelup": "^4.3.0",
"buffer-xor": "^2.0.1",
"ethereumjs-util": "^7.0.4",
"ethereumjs-util": "^7.0.5",
"miller-rabin": "^4.0.0"
},
"devDependencies": {
Expand Down
78 changes: 78 additions & 0 deletions packages/tx/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,84 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
(modification: no type change headlines) and this project adheres to
[Semantic Versioning](http://semver.org/spec/v2.0.0.html).

## [3.0.0] - [UNRELEASED]

### New Package Name

**Attention!** This new version is part of a series of EthereumJS releases all moving to a new scoped package name format. In this case the library is renamed as follows:

- `ethereumjs-tx` -> `@ethereumjs/tx`

Please update your library references accordingly or install with:

```shell
npm i @ethereumjs/tx
```

### Major Refactoring - Breaking Changes

This release is a major refactoring of the transaction library to simplify and strengthen its code base.

#### New Constructor Params

The constructor used to accept a varying amount of options but now has the following shape:

```typescript
Transaction(
common: Common | undefined,
nonce: BN,
gasPrice: BN,
gasLimit: BN,
to: Address | undefined,
value: BN,
data: Buffer,
v?: BN,
r?: BN,
s?: BN,
)
```

Initializing from other data types is assisted with new static factory helpers `fromTxData`, `fromRlpSerializedTx`, and `fromValuesArray`.

Examples:

```typescript
// Initializing from serialized data
const s1 = tx1.serialize().toString('hex')
const tx = Transaction.fromRlpSerializedTx(toBuffer('0x' + s1))

// Initializing with object
const txData = {
gasPrice: 1000,
gasLimit: 10000000,
value: 42,
}
const tx = Transaction.fromTxData(txData)

// Initializing from array of 0x-prefixed strings.
// First, convert to array of Buffers.
const arr = txFixture.raw.map(toBuffer)
const tx = Transaction.fromValuesArray(arr)
```

Learn more about the full API in the [docs](./docs/README.md).

#### Immutability

The returned transaction is now frozen and immutable. To work with a maliable transaction, copy it with `const fakeTx = Object.create(tx)`.

#### from

The `tx.from` alias was removed, please use `const from = tx.getSenderAddress()`.

#### Message to sign

Getting a message to sign has been changed from calling `tx.hash(false)` to `tx.getMessageToSign()`.

#### Fake Transaction

The `FakeTransaction` class was removed since its functionality can now be implemented with less code. To create a fake tansaction for use in e.g. `VM.runTx()` overwrite `getSenderAddress` with your own `Address`. See a full example in the section in the [README](./README.md#fake-transaction).

## [2.1.2] - 2019-12-19

- Added support for the `MuirGlacier` HF by updating the `ethereumjs-common` dependency
Expand Down
Loading

1 comment on commit b1429b9

@github-actions
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Benchmark

Benchmark suite Current: b1429b9 Previous: d15e7be Ratio
Block 9422905 1764 ops/sec (±2.80%) 1742 ops/sec (±4.44%) 0.99
Block 9422906 1765 ops/sec (±2.91%) 1781 ops/sec (±6.65%) 1.01
Block 9422907 1666 ops/sec (±8.20%) 1664 ops/sec (±9.40%) 1.00
Block 9422908 1748 ops/sec (±1.26%) 1744 ops/sec (±1.58%) 1.00
Block 9422909 1730 ops/sec (±1.04%) 1727 ops/sec (±1.33%) 1.00
Block 9422910 1697 ops/sec (±1.50%) 1705 ops/sec (±1.55%) 1.00
Block 9422911 1655 ops/sec (±1.24%) 1737 ops/sec (±1.18%) 1.05
Block 9422912 1254 ops/sec (±13.98%) 1462 ops/sec (±12.55%) 1.17
Block 9422913 1633 ops/sec (±1.39%) 1341 ops/sec (±13.08%) 0.82
Block 9422914 1614 ops/sec (±1.58%) 1663 ops/sec (±1.63%) 1.03

This comment was automatically generated by workflow using github-action-benchmark.

Please sign in to comment.