Skip to content

Commit

Permalink
consortium-v2: fix the EOA check of system transaction (axieinfinity#431
Browse files Browse the repository at this point in the history
)

The EOA check wants to make sure that the sender of system transaction has no
code. The code hash of existing account that has no code is
crypto.Keccak256Hash(nil). Meanwhile, an empty/non-existing account's code hash
is 0x000...00. Currently, we miss the case for empty account, which makes the
system transaction from empty account be rejected.
  • Loading branch information
minh-bq authored Apr 5, 2024
1 parent 4a18ec4 commit dd02049
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 1 deletion.
4 changes: 3 additions & 1 deletion consensus/consortium/common/contract.go
Original file line number Diff line number Diff line change
Expand Up @@ -312,7 +312,9 @@ func ApplyTransaction(msg types.Message, opts *ApplyTransactOpts) (err error) {
expectedHash := signer.Hash(expectedTx)

sender := msg.From()
if codeHash := opts.State.GetCodeHash(sender); codeHash != crypto.Keccak256Hash(nil) {
// An empty/non-existing account's code hash is 0x000...00, while an existing account with no code has code hash
// that is equal to crypto.Keccak256Hash(nil)
if codeHash := opts.State.GetCodeHash(sender); codeHash != crypto.Keccak256Hash(nil) && codeHash != (common.Hash{}) {
return fmt.Errorf("%w: address %v, codehash: %s", core.ErrSenderNoEOA, sender.Hex(), codeHash)
}

Expand Down
36 changes: 36 additions & 0 deletions consensus/consortium/common/contract_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,10 +48,46 @@ func TestApplyTransactionSender(t *testing.T) {
Signer: signer,
},
)
// Sender is an empty account, we must not get core.ErrSenderNoEOA
if errors.Is(err, core.ErrSenderNoEOA) {
t.Fatalf("Don't expect err: %s, have %s", core.ErrSenderNoEOA, err)
}

// Sender is not an empty account but still has no code, we must
// not get core.ErrSenderNoEOA
state.SetBalance(sender, common.Big1)
err = ApplyTransaction(
msg,
&ApplyTransactOpts{
ApplyMessageOpts: &ApplyMessageOpts{
State: state,
Header: &types.Header{},
},
Signer: signer,
},
)
if errors.Is(err, core.ErrSenderNoEOA) {
t.Fatalf("Don't expect err: %s, have %s", core.ErrSenderNoEOA, err)
}

// Sender has code, is not an EOA
state.SetCode(sender, []byte{0x1})
err = ApplyTransaction(
msg,
&ApplyTransactOpts{
ApplyMessageOpts: &ApplyMessageOpts{
State: state,
Header: &types.Header{},
},
Signer: signer,
},
)
if !errors.Is(err, core.ErrSenderNoEOA) {
t.Fatalf("Expect err: %s, have %s", core.ErrSenderNoEOA, err)
}

// Sender is an EOA but the sender of system transaction
// does not match with coinbase
state.SetCode(sender, []byte{})
coinbase := common.Address{0x2}
err = ApplyTransaction(
Expand Down

0 comments on commit dd02049

Please sign in to comment.