Skip to content

Commit a569e6d

Browse files
authored
Merge branch 'master' into checkpoint-trie-cache
2 parents 66aa28a + 83e591a commit a569e6d

File tree

4 files changed

+101
-10
lines changed

4 files changed

+101
-10
lines changed

packages/tx/src/transaction.ts

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -59,17 +59,19 @@ export default class Transaction {
5959

6060
const [nonce, gasPrice, gasLimit, to, value, data, v, r, s] = values
6161

62+
const emptyBuffer = Buffer.from([])
63+
6264
return new Transaction(
6365
{
6466
nonce: new BN(nonce),
6567
gasPrice: new BN(gasPrice),
6668
gasLimit: new BN(gasLimit),
6769
to: to && to.length > 0 ? new Address(to) : undefined,
6870
value: new BN(value),
69-
data: data || Buffer.from([]),
70-
v: v ? new BN(v) : undefined,
71-
r: r ? new BN(r) : undefined,
72-
s: s ? new BN(s) : undefined,
71+
data: data ?? emptyBuffer,
72+
v: !v?.equals(emptyBuffer) ? new BN(v) : undefined,
73+
r: !r?.equals(emptyBuffer) ? new BN(r) : undefined,
74+
s: !s?.equals(emptyBuffer) ? new BN(s) : undefined,
7375
},
7476
opts
7577
)
@@ -89,9 +91,9 @@ export default class Transaction {
8991
this.to = to ? new Address(toBuffer(to)) : undefined
9092
this.value = new BN(toBuffer(value))
9193
this.data = toBuffer(data)
92-
this.v = new BN(toBuffer(v))
93-
this.r = new BN(toBuffer(r))
94-
this.s = new BN(toBuffer(s))
94+
this.v = v ? new BN(toBuffer(v)) : undefined
95+
this.r = r ? new BN(toBuffer(r)) : undefined
96+
this.s = s ? new BN(toBuffer(s)) : undefined
9597

9698
const validateCannotExceedMaxInteger = {
9799
nonce: this.nonce,

packages/tx/test/api.ts

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -335,6 +335,43 @@ tape('[Transaction]: Basic functions', function (t) {
335335
st.end()
336336
})
337337

338+
t.test('returns correct values for isSigned', function (st) {
339+
let tx = Transaction.fromTxData({})
340+
st.notOk(tx.isSigned())
341+
342+
const txData: TxData = {
343+
data: '0x7cf5dab00000000000000000000000000000000000000000000000000000000000000005',
344+
gasLimit: '0x15f90',
345+
gasPrice: '0x1',
346+
nonce: '0x01',
347+
to: '0xd9024df085d09398ec76fbed18cac0e1149f50dc',
348+
value: '0x0',
349+
}
350+
const privateKey = Buffer.from(
351+
'4646464646464646464646464646464646464646464646464646464646464646',
352+
'hex'
353+
)
354+
tx = Transaction.fromTxData(txData)
355+
st.notOk(tx.isSigned())
356+
tx = tx.sign(privateKey)
357+
st.ok(tx.isSigned())
358+
359+
tx = new Transaction(txData)
360+
st.notOk(tx.isSigned())
361+
const rawUnsigned = tx.serialize()
362+
tx = tx.sign(privateKey)
363+
const rawSigned = tx.serialize()
364+
st.ok(tx.isSigned())
365+
366+
tx = Transaction.fromRlpSerializedTx(rawUnsigned)
367+
st.notOk(tx.isSigned())
368+
tx = tx.sign(privateKey)
369+
st.ok(tx.isSigned())
370+
tx = Transaction.fromRlpSerializedTx(rawSigned)
371+
st.ok(tx.isSigned())
372+
st.end()
373+
})
374+
338375
t.test(
339376
'throws when creating a a transaction with incompatible chainid and v value',
340377
function (st) {

packages/vm/lib/runTx.ts

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,12 @@ export interface RunTxOpts {
2727
* If true, skips the balance check
2828
*/
2929
skipBalance?: boolean
30+
31+
/**
32+
* If true, skips the validation of the tx's gas limit
33+
* agains the block's gas limit.
34+
*/
35+
skipBlockGasLimitValidation?: boolean
3036
}
3137

3238
/**
@@ -66,7 +72,10 @@ export default async function runTx(this: VM, opts: RunTxOpts): Promise<RunTxRes
6672
// create a reasonable default if no block is given
6773
opts.block = opts.block ?? Block.fromBlockData({}, { common: opts.tx.common })
6874

69-
if (opts.block.header.gasLimit.lt(opts.tx.gasLimit)) {
75+
if (
76+
opts.skipBlockGasLimitValidation !== true &&
77+
opts.block.header.gasLimit.lt(opts.tx.gasLimit)
78+
) {
7079
throw new Error('tx has a higher gas limit than the block')
7180
}
7281

packages/vm/tests/api/runTx.spec.ts

Lines changed: 45 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import tape from 'tape'
2-
import { Address, BN, MAX_INTEGER } from 'ethereumjs-util'
2+
import { Account, Address, BN, MAX_INTEGER } from 'ethereumjs-util'
3+
import { Block } from '@ethereumjs/block'
34
import Common from '@ethereumjs/common'
45
import { Transaction } from '@ethereumjs/tx'
56
import VM from '../../lib'
@@ -32,7 +33,7 @@ tape('runTx', (t) => {
3233
t.test('should fail to run without signature', async (st) => {
3334
const tx = getTransaction(false)
3435
shouldFail(st, suite.runTx({ tx }), (e: Error) =>
35-
st.ok(e.message.includes('Invalid Signature'), 'should fail with appropriate error')
36+
st.ok(e.message.includes('not signed'), 'should fail with appropriate error')
3637
)
3738
st.end()
3839
})
@@ -144,6 +145,48 @@ tape('should clear storage cache after every transaction', async (t) => {
144145
t.end()
145146
})
146147

148+
tape('should be possible to disable the block gas limit validation', async (t) => {
149+
const vm = new VM()
150+
151+
const privateKey = Buffer.from(
152+
'e331b6d69882b4cb4ea581d88e0b604039a3de5967688d3dcffdd2270c0fd109',
153+
'hex'
154+
)
155+
const address = Address.fromPrivateKey(privateKey)
156+
const initialBalance = new BN(10).pow(new BN(18))
157+
158+
const account = await vm.stateManager.getAccount(address)
159+
await vm.stateManager.putAccount(
160+
address,
161+
Account.fromAccountData({ ...account, balance: initialBalance })
162+
)
163+
164+
const transferCost = 21000
165+
166+
const unsignedTx = Transaction.fromTxData({
167+
to: address,
168+
gasLimit: transferCost,
169+
gasPrice: 1,
170+
nonce: 0,
171+
})
172+
173+
const tx = unsignedTx.sign(privateKey)
174+
175+
const block = Block.fromBlockData({
176+
header: { gasLimit: transferCost - 1 },
177+
})
178+
179+
const result = await vm.runTx({
180+
tx,
181+
block,
182+
skipBlockGasLimitValidation: true,
183+
})
184+
185+
t.equals(result.execResult.exceptionError, undefined)
186+
187+
t.end()
188+
})
189+
147190
// The following test tries to verify that running a tx
148191
// would work, even when stateManager is not using a cache.
149192
// It fails at the moment, and has been therefore commented.

0 commit comments

Comments
 (0)