Skip to content

Commit

Permalink
Merge branch 'AB-1214' into 'main'
Browse files Browse the repository at this point in the history
Resolve AB-1214

Closes AB-1214

See merge request alphabill/alphabill!665
  • Loading branch information
GT-Kristjan committed Sep 27, 2023
2 parents 277a86f + c78d458 commit b2d2e49
Show file tree
Hide file tree
Showing 3 changed files with 99 additions and 18 deletions.
9 changes: 2 additions & 7 deletions internal/txsystem/evm/statedb/units.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ import (

var (
_ abstate.UnitData = (*StateObject)(nil)
_ abstate.UnitData = (*AlphaBillLink)(nil)

emptyCodeHash = crypto.Keccak256(nil)
)
Expand Down Expand Up @@ -74,15 +73,11 @@ func (s *StateObject) Copy() abstate.UnitData {
return nil
}

var link *AlphaBillLink
if s.AlphaBill != nil {
link = s.AlphaBill.Copy().(*AlphaBillLink)
}
return &StateObject{
Address: common.BytesToAddress(bytes.Clone(s.Address.Bytes())),
Account: s.Account.Copy(),
Storage: s.Storage.Copy(),
AlphaBill: link,
AlphaBill: s.AlphaBill.Copy(),
suicided: s.suicided,
}
}
Expand All @@ -96,7 +91,7 @@ func (f *AlphaBillLink) SummaryValueInput() uint64 {
return 0
}

func (f *AlphaBillLink) Copy() abstate.UnitData {
func (f *AlphaBillLink) Copy() *AlphaBillLink {
if f == nil {
return nil
}
Expand Down
25 changes: 17 additions & 8 deletions internal/txsystem/evm/tx_system.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ type TxSystem struct {
genericTxValidators []txsystem.GenericTransactionValidator
beginBlockFunctions []func(blockNumber uint64) error
endBlockFunctions []func(blockNumber uint64) error
roundCommitted bool
}

func NewEVMTxSystem(systemIdentifier []byte, opts ...Option) (*TxSystem, error) {
Expand Down Expand Up @@ -92,6 +93,7 @@ func (m *TxSystem) getState() (txsystem.State, error) {

func (m *TxSystem) BeginBlock(blockNr uint64) error {
m.currentBlockNumber = blockNr
m.roundCommitted = false
for _, function := range m.beginBlockFunctions {
if err := function(blockNr); err != nil {
return fmt.Errorf("begin block function call failed: %w", err)
Expand All @@ -100,6 +102,13 @@ func (m *TxSystem) BeginBlock(blockNr uint64) error {
return nil
}

func (m *TxSystem) pruneLogs(blockNr uint64) error {
if err := m.logPruner.Prune(blockNr - 1); err != nil {
return fmt.Errorf("unable to prune state: %w", err)
}
return nil
}

func (m *TxSystem) Execute(tx *types.TransactionOrder) (sm *types.ServerMetadata, err error) {
u, _ := m.state.GetUnit(tx.UnitID(), false)
ctx := &txsystem.TxValidationContext{
Expand Down Expand Up @@ -149,13 +158,6 @@ func (m *TxSystem) Execute(tx *types.TransactionOrder) (sm *types.ServerMetadata
return sm, err
}

func (m *TxSystem) pruneLogs(blockNr uint64) error {
if err := m.logPruner.Prune(blockNr - 1); err != nil {
return fmt.Errorf("unable to prune state: %w", err)
}
return nil
}

func (m *TxSystem) EndBlock() (txsystem.State, error) {
for _, function := range m.endBlockFunctions {
if err := function(m.currentBlockNumber); err != nil {
Expand All @@ -166,11 +168,18 @@ func (m *TxSystem) EndBlock() (txsystem.State, error) {
}

func (m *TxSystem) Revert() {
if m.roundCommitted {
return
}
m.logPruner.Remove(m.currentBlockNumber)
m.state.Revert()
}

func (m *TxSystem) Commit() error {
m.logPruner.Remove(m.currentBlockNumber - 1)
return m.state.Commit()
err := m.state.Commit()
if err == nil {
m.roundCommitted = true
}
return err
}
83 changes: 80 additions & 3 deletions internal/txsystem/evm/tx_system_integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ func TestEVMPartition_DeployAndCallContract(t *testing.T) {
require.NoError(t, err)

// call contract - increment
callContractTx := createCallContractTx(from, contractAddr, cABI.Methods["increment"].ID, t)
callContractTx := createCallContractTx(from, contractAddr, cABI.Methods["increment"].ID, 2, t)
require.NoError(t, evmPartition.SubmitTx(callContractTx))
require.Eventually(t, testpartition.BlockchainContainsTx(evmPartition, callContractTx), test.WaitDuration, test.WaitTick)
_, _, txRecord, err = evmPartition.GetTxProof(callContractTx)
Expand All @@ -106,6 +106,83 @@ func TestEVMPartition_DeployAndCallContract(t *testing.T) {
require.Nil(t, entry.Data)
}

func TestEVMPartition_Revert_test(t *testing.T) {
from := test.RandomBytes(20)
cABI, err := abi.JSON(bytes.NewBuffer([]byte(counterABI)))
require.NoError(t, err)
system, err := NewEVMTxSystem(systemIdentifier, WithInitialAddressAndBalance(from, big.NewInt(oneEth)), WithBlockDB(memorydb.New())) // 1 ETH
require.NoError(t, err)

// Simulate round 1
require.NoError(t, system.BeginBlock(1))
// transfer
to := test.RandomBytes(20)
transferTx := createTransferTx(t, from, to)
meta, err := system.Execute(transferTx)
require.NoError(t, err)
require.NotNil(t, meta)
// deploy contract
deployContractTx := createDeployContractTx(t, from)
meta, err = system.Execute(deployContractTx)
require.NoError(t, err)
require.NotNil(t, meta)
require.Equal(t, types.TxStatusSuccessful, meta.SuccessIndicator)
var details ProcessingDetails
require.NoError(t, cbor.Unmarshal(meta.ProcessingDetails, &details))
require.Equal(t, details.ErrorDetails, "")
contractAddr := evmcrypto.CreateAddress(common.BytesToAddress(from), 1)
require.Equal(t, details.ContractAddr, contractAddr)
require.NotEmpty(t, details.ReturnData) // increment does not return anything
// call contract - increment
callContractTx := createCallContractTx(from, contractAddr, cABI.Methods["increment"].ID, 2, t)
meta, err = system.Execute(callContractTx)
require.NoError(t, err)
require.NotNil(t, meta)
require.Equal(t, types.TxStatusSuccessful, meta.SuccessIndicator)
require.NoError(t, cbor.Unmarshal(meta.ProcessingDetails, &details))
require.Equal(t, details.ErrorDetails, "")
require.Equal(t, details.ContractAddr, common.Address{})
// expect count uint256 = 1
count := uint256.NewInt(1)
require.EqualValues(t, count.PaddedBytes(32), details.ReturnData)
require.Len(t, details.Logs, 1)
entry := details.Logs[0]
require.Len(t, entry.Topics, 2)
require.Equal(t, common.BytesToHash(evmcrypto.Keccak256([]byte(cABI.Events["Increment"].Sig))), entry.Topics[0])
require.Equal(t, common.BytesToHash(count.PaddedBytes(32)), entry.Topics[1])
require.Equal(t, contractAddr, entry.Address)
require.Nil(t, entry.Data)
round1EndState, err := system.EndBlock()
require.NoError(t, err)
require.NotNil(t, round1EndState)
require.NoError(t, system.Commit())
// Round 2, but this gets reverted
require.NoError(t, system.BeginBlock(2))
callContractTx = createCallContractTx(from, contractAddr, cABI.Methods["increment"].ID, 3, t)
meta, err = system.Execute(callContractTx)
require.NoError(t, err)
require.NotNil(t, meta)
require.Equal(t, types.TxStatusSuccessful, meta.SuccessIndicator)
require.NoError(t, cbor.Unmarshal(meta.ProcessingDetails, &details))
require.Equal(t, details.ErrorDetails, "")
require.Equal(t, details.ContractAddr, common.Address{})
count = uint256.NewInt(2)
require.EqualValues(t, count.PaddedBytes(32), details.ReturnData)
round2EndState, err := system.EndBlock()
require.NoError(t, err)
require.NotNil(t, round2EndState)
require.NotEqualValues(t, round1EndState.Root(), round2EndState.Root())
// revert round 2 and do it over again
system.Revert()
revertedState, err := system.StateSummary()
require.NoError(t, err)
require.Equal(t, round1EndState.Root(), revertedState.Root())
// Round 2 again, but this time with empty block, state should not change from round 1
require.NoError(t, system.BeginBlock(2))
round2EndState, err = system.EndBlock()
require.NotEqualValues(t, round2EndState.Root(), round1EndState.Root())
}

func createTransferTx(t *testing.T, from []byte, to []byte) *types.TransactionOrder {
evmAttr := &TxAttributes{
From: from,
Expand All @@ -128,14 +205,14 @@ func createTransferTx(t *testing.T, from []byte, to []byte) *types.TransactionOr
}
}

func createCallContractTx(from []byte, addr common.Address, methodID []byte, t *testing.T) *types.TransactionOrder {
func createCallContractTx(from []byte, addr common.Address, methodID []byte, nonce uint64, t *testing.T) *types.TransactionOrder {
evmAttr := &TxAttributes{
From: from,
To: addr.Bytes(),
Data: methodID,
Value: big.NewInt(0),
Gas: 100000,
Nonce: 2,
Nonce: nonce,
}
attrBytes, err := cbor.Marshal(evmAttr)
require.NoError(t, err)
Expand Down

0 comments on commit b2d2e49

Please sign in to comment.