mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-27 07:06:42 +00:00
feat: include L1 message with insufficient balance (#462)
* feat: include L1 message with insufficient balance * fix tests * add comment * bump version
This commit is contained in:
parent
e5dfc7535a
commit
447fed2573
3 changed files with 65 additions and 20 deletions
|
|
@ -374,7 +374,10 @@ func (st *StateTransition) TransitionDb() (*ExecutionResult, error) {
|
||||||
st.gas -= gas
|
st.gas -= gas
|
||||||
|
|
||||||
// Check clause 6
|
// Check clause 6
|
||||||
if msg.Value().Sign() > 0 && !st.evm.Context.CanTransfer(st.state, msg.From(), msg.Value()) {
|
// Note: If this is an L1MessageTx, we will not return a top-level ErrInsufficientFundsForTransfer.
|
||||||
|
// Instead, we return ErrInsufficientBalance from within st.evm.Call. This means that such transactions
|
||||||
|
// will revert but they can be included in a valid block. This is necessary for supporting enforced txs.
|
||||||
|
if msg.Value().Sign() > 0 && !st.evm.Context.CanTransfer(st.state, msg.From(), msg.Value()) && !msg.IsL1MessageTx() {
|
||||||
return nil, fmt.Errorf("%w: address %v", ErrInsufficientFundsForTransfer, msg.From().Hex())
|
return nil, fmt.Errorf("%w: address %v", ErrInsufficientFundsForTransfer, msg.From().Hex())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -515,7 +515,7 @@ func TestL1MsgCorrectOrder(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func l1MessageTest(t *testing.T, msgs []types.L1MessageTx, withL2Tx bool, callback func(i int, block *types.Block, db ethdb.Database, w *worker) bool) {
|
func l1MessageTest(t *testing.T, msgs []types.L1MessageTx, withL2Tx bool, callback func(i int, block *types.Block, db ethdb.Database, w *worker, bc *core.BlockChain) bool) {
|
||||||
var (
|
var (
|
||||||
engine consensus.Engine
|
engine consensus.Engine
|
||||||
chainConfig *params.ChainConfig
|
chainConfig *params.ChainConfig
|
||||||
|
|
@ -558,7 +558,7 @@ func l1MessageTest(t *testing.T, msgs []types.L1MessageTx, withL2Tx bool, callba
|
||||||
w.start()
|
w.start()
|
||||||
|
|
||||||
// call once before first block
|
// call once before first block
|
||||||
callback(0, nil, db, w)
|
callback(0, nil, db, w, chain)
|
||||||
|
|
||||||
// timeout for all blocks
|
// timeout for all blocks
|
||||||
globalTimeout := time.After(3 * time.Second)
|
globalTimeout := time.After(3 * time.Second)
|
||||||
|
|
@ -574,7 +574,7 @@ func l1MessageTest(t *testing.T, msgs []types.L1MessageTx, withL2Tx bool, callba
|
||||||
case ev := <-sub.Chan():
|
case ev := <-sub.Chan():
|
||||||
block := ev.Data.(core.NewMinedBlockEvent).Block
|
block := ev.Data.(core.NewMinedBlockEvent).Block
|
||||||
|
|
||||||
if done := callback(ii, block, db, w); done {
|
if done := callback(ii, block, db, w, chain); done {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -594,7 +594,7 @@ func TestL1SingleMessageOverGasLimit(t *testing.T) {
|
||||||
{QueueIndex: 2, Gas: 21016, To: &common.Address{1}, Data: []byte{0x01}, Sender: common.Address{3}}, // different sender
|
{QueueIndex: 2, Gas: 21016, To: &common.Address{1}, Data: []byte{0x01}, Sender: common.Address{3}}, // different sender
|
||||||
}
|
}
|
||||||
|
|
||||||
l1MessageTest(t, msgs, false, func(blockNum int, block *types.Block, db ethdb.Database, w *worker) bool {
|
l1MessageTest(t, msgs, false, func(blockNum int, block *types.Block, db ethdb.Database, w *worker, bc *core.BlockChain) bool {
|
||||||
switch blockNum {
|
switch blockNum {
|
||||||
case 0:
|
case 0:
|
||||||
return false
|
return false
|
||||||
|
|
@ -630,7 +630,7 @@ func TestL1CombinedMessagesOverGasLimit(t *testing.T) {
|
||||||
{QueueIndex: 2, Gas: 21016, To: &common.Address{1}, Data: []byte{0x01}, Sender: common.Address{3}}, // different sender
|
{QueueIndex: 2, Gas: 21016, To: &common.Address{1}, Data: []byte{0x01}, Sender: common.Address{3}}, // different sender
|
||||||
}
|
}
|
||||||
|
|
||||||
l1MessageTest(t, msgs, false, func(blockNum int, block *types.Block, db ethdb.Database, w *worker) bool {
|
l1MessageTest(t, msgs, false, func(blockNum int, block *types.Block, db ethdb.Database, w *worker, bc *core.BlockChain) bool {
|
||||||
switch blockNum {
|
switch blockNum {
|
||||||
case 0:
|
case 0:
|
||||||
return false
|
return false
|
||||||
|
|
@ -674,7 +674,7 @@ func TestLargeL1MessageSkipPayloadCheck(t *testing.T) {
|
||||||
{QueueIndex: 2, Gas: 21016, To: &common.Address{1}, Data: []byte{0x01}, Sender: common.Address{3}}, // different sender
|
{QueueIndex: 2, Gas: 21016, To: &common.Address{1}, Data: []byte{0x01}, Sender: common.Address{3}}, // different sender
|
||||||
}
|
}
|
||||||
|
|
||||||
l1MessageTest(t, msgs, true, func(blockNum int, block *types.Block, db ethdb.Database, w *worker) bool {
|
l1MessageTest(t, msgs, true, func(blockNum int, block *types.Block, db ethdb.Database, w *worker, bc *core.BlockChain) bool {
|
||||||
switch blockNum {
|
switch blockNum {
|
||||||
case 0:
|
case 0:
|
||||||
return false
|
return false
|
||||||
|
|
@ -708,15 +708,17 @@ func TestLargeL1MessageSkipPayloadCheck(t *testing.T) {
|
||||||
func TestSkipMessageWithStrangeError(t *testing.T) {
|
func TestSkipMessageWithStrangeError(t *testing.T) {
|
||||||
assert := assert.New(t)
|
assert := assert.New(t)
|
||||||
|
|
||||||
// message #0 is skipped because of `Value`
|
|
||||||
// TODO: trigger skipping in some other way after this behaviour is changed
|
|
||||||
msgs := []types.L1MessageTx{
|
msgs := []types.L1MessageTx{
|
||||||
{QueueIndex: 0, Gas: 25100, To: &common.Address{1}, Data: []byte{0x01}, Sender: common.Address{2}, Value: big.NewInt(1)},
|
// message #0 is skipped because of `GasLimit`
|
||||||
|
// (cannot happen in practice, this is checked in the contracts)
|
||||||
|
{QueueIndex: 0, Gas: 20000000, To: &common.Address{1}, Data: []byte{0x01}, Sender: common.Address{2}},
|
||||||
|
|
||||||
|
// messages #1 and #2 are correct
|
||||||
{QueueIndex: 1, Gas: 21016, To: &common.Address{1}, Data: []byte{0x01}, Sender: common.Address{2}},
|
{QueueIndex: 1, Gas: 21016, To: &common.Address{1}, Data: []byte{0x01}, Sender: common.Address{2}},
|
||||||
{QueueIndex: 2, Gas: 21016, To: &common.Address{1}, Data: []byte{0x01}, Sender: common.Address{3}},
|
{QueueIndex: 2, Gas: 21016, To: &common.Address{1}, Data: []byte{0x01}, Sender: common.Address{3}},
|
||||||
}
|
}
|
||||||
|
|
||||||
l1MessageTest(t, msgs, false, func(blockNum int, block *types.Block, db ethdb.Database, w *worker) bool {
|
l1MessageTest(t, msgs, false, func(blockNum int, block *types.Block, db ethdb.Database, w *worker, bc *core.BlockChain) bool {
|
||||||
switch blockNum {
|
switch blockNum {
|
||||||
case 0:
|
case 0:
|
||||||
return false
|
return false
|
||||||
|
|
@ -742,18 +744,58 @@ func TestSkipMessageWithStrangeError(t *testing.T) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestL1MessageWithInsufficientBalanceNotSkipped(t *testing.T) {
|
||||||
|
assert := assert.New(t)
|
||||||
|
|
||||||
|
msgs := []types.L1MessageTx{
|
||||||
|
// message #0 sends more funds than available in the sender account
|
||||||
|
{QueueIndex: 0, Gas: 25100, To: &common.Address{1}, Data: make([]byte, 1025), Sender: common.Address{2}, Value: big.NewInt(1)},
|
||||||
|
|
||||||
|
// #message #1 is a correct msg
|
||||||
|
{QueueIndex: 1, Gas: 25100, To: &common.Address{1}, Data: make([]byte, 1025), Sender: common.Address{2}},
|
||||||
|
}
|
||||||
|
|
||||||
|
l1MessageTest(t, msgs, false, func(blockNum int, block *types.Block, db ethdb.Database, w *worker, bc *core.BlockChain) bool {
|
||||||
|
switch blockNum {
|
||||||
|
case 0:
|
||||||
|
return false
|
||||||
|
case 1:
|
||||||
|
// include both #0 and #1
|
||||||
|
assert.Equal(2, len(block.Transactions()))
|
||||||
|
assert.True(block.Transactions()[0].IsL1MessageTx())
|
||||||
|
assert.Equal(uint64(0), block.Transactions()[0].AsL1MessageTx().QueueIndex)
|
||||||
|
assert.True(block.Transactions()[1].IsL1MessageTx())
|
||||||
|
assert.Equal(uint64(1), block.Transactions()[1].AsL1MessageTx().QueueIndex)
|
||||||
|
|
||||||
|
// #0 fails, #1 succeeds
|
||||||
|
receipts := bc.GetReceiptsByHash(block.Hash())
|
||||||
|
assert.Equal(2, len(receipts))
|
||||||
|
assert.Equal(types.ReceiptStatusFailed, receipts[0].Status)
|
||||||
|
assert.Equal(types.ReceiptStatusSuccessful, receipts[1].Status)
|
||||||
|
|
||||||
|
// db is updated correctly
|
||||||
|
queueIndex := rawdb.ReadFirstQueueIndexNotInL2Block(db, block.Hash())
|
||||||
|
assert.NotNil(queueIndex)
|
||||||
|
assert.Equal(uint64(2), *queueIndex)
|
||||||
|
|
||||||
|
return true
|
||||||
|
default:
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
func TestSkipAllL1MessagesInBlock(t *testing.T) {
|
func TestSkipAllL1MessagesInBlock(t *testing.T) {
|
||||||
assert := assert.New(t)
|
assert := assert.New(t)
|
||||||
|
|
||||||
// messages are skipped because of `Value`
|
// messages are skipped because of `GasLimit`
|
||||||
// TODO: trigger skipping in some other way after this behaviour is changed
|
|
||||||
msgs := []types.L1MessageTx{
|
msgs := []types.L1MessageTx{
|
||||||
{QueueIndex: 0, Gas: 25100, To: &common.Address{1}, Data: []byte{0x01}, Sender: common.Address{2}, Value: big.NewInt(1)},
|
{QueueIndex: 0, Gas: 20000000, To: &common.Address{1}, Data: []byte{0x01}, Sender: common.Address{2}},
|
||||||
{QueueIndex: 1, Gas: 21016, To: &common.Address{1}, Data: []byte{0x01}, Sender: common.Address{2}, Value: big.NewInt(1)},
|
{QueueIndex: 1, Gas: 20000000, To: &common.Address{1}, Data: []byte{0x01}, Sender: common.Address{2}},
|
||||||
{QueueIndex: 2, Gas: 21016, To: &common.Address{1}, Data: []byte{0x01}, Sender: common.Address{3}, Value: big.NewInt(1)},
|
{QueueIndex: 2, Gas: 20000000, To: &common.Address{1}, Data: []byte{0x01}, Sender: common.Address{3}},
|
||||||
}
|
}
|
||||||
|
|
||||||
l1MessageTest(t, msgs, true, func(blockNum int, block *types.Block, db ethdb.Database, w *worker) bool {
|
l1MessageTest(t, msgs, true, func(blockNum int, block *types.Block, db ethdb.Database, w *worker, bc *core.BlockChain) bool {
|
||||||
switch blockNum {
|
switch blockNum {
|
||||||
case 0:
|
case 0:
|
||||||
return false
|
return false
|
||||||
|
|
@ -785,7 +827,7 @@ func TestOversizedTxThenNormal(t *testing.T) {
|
||||||
{QueueIndex: 2, Gas: 21016, To: &common.Address{1}, Data: []byte{0x01}, Sender: common.Address{3}},
|
{QueueIndex: 2, Gas: 21016, To: &common.Address{1}, Data: []byte{0x01}, Sender: common.Address{3}},
|
||||||
}
|
}
|
||||||
|
|
||||||
l1MessageTest(t, msgs, false, func(blockNum int, block *types.Block, db ethdb.Database, w *worker) bool {
|
l1MessageTest(t, msgs, false, func(blockNum int, block *types.Block, db ethdb.Database, w *worker, bc *core.BlockChain) bool {
|
||||||
switch blockNum {
|
switch blockNum {
|
||||||
case 0:
|
case 0:
|
||||||
// schedule to skip 2nd call to ccc
|
// schedule to skip 2nd call to ccc
|
||||||
|
|
@ -933,7 +975,7 @@ func TestSkippedTransactionDatabaseEntries(t *testing.T) {
|
||||||
{QueueIndex: 1, Gas: 21016, To: &common.Address{1}, Data: []byte{0x01}, Sender: common.Address{2}},
|
{QueueIndex: 1, Gas: 21016, To: &common.Address{1}, Data: []byte{0x01}, Sender: common.Address{2}},
|
||||||
}
|
}
|
||||||
|
|
||||||
l1MessageTest(t, msgs, false, func(blockNum int, block *types.Block, db ethdb.Database, w *worker) bool {
|
l1MessageTest(t, msgs, false, func(blockNum int, block *types.Block, db ethdb.Database, w *worker, bc *core.BlockChain) bool {
|
||||||
switch blockNum {
|
switch blockNum {
|
||||||
case 0:
|
case 0:
|
||||||
return false
|
return false
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,7 @@ import (
|
||||||
const (
|
const (
|
||||||
VersionMajor = 5 // Major version component of the current release
|
VersionMajor = 5 // Major version component of the current release
|
||||||
VersionMinor = 8 // Minor version component of the current release
|
VersionMinor = 8 // Minor version component of the current release
|
||||||
VersionPatch = 0 // Patch version component of the current release
|
VersionPatch = 1 // Patch version component of the current release
|
||||||
VersionMeta = "mainnet" // Version metadata to append to the version string
|
VersionMeta = "mainnet" // Version metadata to append to the version string
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue