63377e34fa
* Get basic getStorage/setStorage stubs working * Clean up tests * Add state_manager * Add StateManager set & getStorage * Add state mananger create function * Add get & increment nonce * Add getCodeContractBytecode * Add GetCodeContractHash * Add getCodeContractHash to the state manager * Add associateCodeContract to state manager * Pass the tests * go fmt * Add stateTransition to test with * Fix tests * Test deploying contract with transition state * Call executeTransaction on contract deployment * Added ExecutionManager deployment * Get contract deployments working * Cleanup logging * Get stubbed ExecutionManager working * Get a simple contract to deploy through the ExecutionManager * Refactor simpleAbiEncode * Revert unnecessary changes * Remove comments * Revert changes outside of this PR * Revert changes outside of this PR * Revert changes outside of this PR * Fix broken tests * Move OVM bytecode & ABI into constants * Add crazy printlines * Remove crazy comments * Add a bunch of debug printlns * Add helper fn for applying msgs to the EVM * Update ExecutionManager bytecode * Shim CREATE for EM to use correct addr * Add SimpleStorage test * Add the EM/SM to all new states * Force all txs to be routed through the EM * Remove unused files * Remove unused comments * Increment nonce after failed tx * Add debug statements * Use evm.Time for timestamp * Change EM deployment, fix broken tests, clean up * Add an OVM test & remove printlns * Fix lint errors & remove final printlns * Final cleanup--remove some comments * Limiting Geth to one transaction per block (#3) * Limiting Geth to one transaction per block * Adding TransitionBatchBuilder to build & submit rollup blocks * Adding L1MessageSender to Transaction (#4) * Adding L1MessageSender to Transaction * Adding logic to omit L1MessageSender in encoding / decoding when nil and never use it in hash computation Co-authored-by: ben-chain <ben@pseudonym.party> * Fixing Geth Tests (#6) Fixing broken tests, skipping tests we intentionally break, and configuring CI within Github Actions * Hex Trie -> Binary Trie (#7) *** Changing Hex Trie to Binary Trie *** Note: This changes and/or comments out a bunch of tests, so if things break down the line, this is likely the cause! * Ingest Block Batches (#8) Handling BlockBatches in Geth at `SendBlockBatches` endpoint (eth_sendBlockBatches) Other: * Adding PR template * Adding ability to set timestamp and making blocks use configured timestamp * Adding ability to encode original tx nonce in calldata * Adding L1MessageSender to Contract Creation Txs * Add L1MessageSender to Message * Increment nonce on CREATE failure * Fix bug where evm.Time=0 * Use state dump with hardcoded EM & SM addrs - ExecutionMgr address should always be 0x0000...dead0000 - StateMgr address should always be 0x0000...dead0001 * Move EM deployment into genesis block maker * Update EM contracts to latest version * Update EM to remove events * Fix the OVM tests * Skip an ungodly number of tests * Fix lint errors * Clean up logging * Cleanup more logs * Use local reference to state manager * Rename applyOvmToState(..) * Remove unneeded check * Clean up logging & add EM ABI panic * Add gas metering to SM & small refactor * Update core/vm/state_manager.go Co-authored-by: Kevin Ho <kevinjho1996@gmail.com> Co-authored-by: Mason Fischer <mason@kissr.co> Co-authored-by: Will Meister <william.k.meister@gmail.com> Co-authored-by: ben-chain <ben@pseudonym.party> Co-authored-by: Kevin Ho <kevinjho1996@gmail.com>
281 lines
14 KiB
Go
281 lines
14 KiB
Go
package tests
|
|
|
|
import (
|
|
"bytes"
|
|
"encoding/binary"
|
|
"encoding/hex"
|
|
"io/ioutil"
|
|
"math/big"
|
|
"strings"
|
|
"testing"
|
|
|
|
"github.com/ethereum/go-ethereum/accounts/abi"
|
|
"github.com/ethereum/go-ethereum/common"
|
|
"github.com/ethereum/go-ethereum/core"
|
|
"github.com/ethereum/go-ethereum/core/rawdb"
|
|
"github.com/ethereum/go-ethereum/core/state"
|
|
"github.com/ethereum/go-ethereum/core/types"
|
|
"github.com/ethereum/go-ethereum/core/vm"
|
|
"github.com/ethereum/go-ethereum/core/vm/runtime"
|
|
"github.com/ethereum/go-ethereum/crypto"
|
|
"github.com/ethereum/go-ethereum/log"
|
|
"github.com/ethereum/go-ethereum/params"
|
|
)
|
|
|
|
var chainConfig params.ChainConfig
|
|
|
|
func init() {
|
|
chainConfig = params.ChainConfig{
|
|
ChainID: big.NewInt(1),
|
|
HomesteadBlock: new(big.Int),
|
|
ByzantiumBlock: new(big.Int),
|
|
ConstantinopleBlock: new(big.Int),
|
|
DAOForkBlock: new(big.Int),
|
|
DAOForkSupport: false,
|
|
EIP150Block: new(big.Int),
|
|
EIP155Block: new(big.Int),
|
|
EIP158Block: new(big.Int),
|
|
}
|
|
}
|
|
|
|
const GAS_LIMIT = 15000000
|
|
|
|
var ZERO_ADDRESS = common.HexToAddress("0000000000000000000000000000000000000000")
|
|
var OTHER_FROM_ADDR = common.HexToAddress("8888888888888888888888888888888888888888")
|
|
|
|
func TestContractCreationAndSimpleStorageTxs(t *testing.T) {
|
|
currentState := newState()
|
|
|
|
// Next we've got to generate & apply a transaction which calls the EM to deploy a new contract
|
|
initCode, _ := hex.DecodeString("608060405234801561001057600080fd5b5060405161026b38038061026b8339818101604052602081101561003357600080fd5b8101908080519060200190929190505050806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550506101d7806100946000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c80633408f73a1461003b578063d3404b6d14610045575b600080fd5b61004361004f565b005b61004d6100fa565b005b600060e060405180807f6f766d534c4f4144282900000000000000000000000000000000000000000000815250600a0190506040518091039020901c905060008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905060405136600082378260181c81538260101c60018201538260081c60028201538260038201536040516207a1208136846000875af160008114156100f657600080fd5b3d82f35b600060e060405180807f6f766d5353544f52452829000000000000000000000000000000000000000000815250600b0190506040518091039020901c905060008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905060405136600082378260181c81538260101c60018201538260081c600282015382600382015360008036836000865af1600081141561019c57600080fd5b5050505056fea265627a7a72315820311a406c97055eec367b660092882e1a174e14333416a3de384439293b7b129264736f6c6343000510003200000000000000000000000000000000000000000000000000000000dead0000")
|
|
|
|
log.Debug("\n\nApplying CREATE SIMPLE STORAGE Tx to State.")
|
|
applyMessageToState(currentState, OTHER_FROM_ADDR, ZERO_ADDRESS, GAS_LIMIT, initCode)
|
|
log.Debug("Complete.")
|
|
|
|
log.Debug("\n\nApplying CALL SIMPLE STORAGE Tx to State.")
|
|
newContractAddr := common.HexToAddress("65486c8ec9167565eBD93c94ED04F0F71d1b5137")
|
|
setStorageInnerCalldata, _ := hex.DecodeString("d3404b6d99999999999999999999999999999999999999999999999999999999999999990101010101010101010101010101010101010101010101010101010101010101")
|
|
getStorageInnerCalldata, _ := hex.DecodeString("3408f73a9999999999999999999999999999999999999999999999999999999999999999")
|
|
|
|
log.Debug("\n\nApplying `set()` SIMPLE STORAGE Tx to State.")
|
|
applyMessageToState(currentState, OTHER_FROM_ADDR, newContractAddr, GAS_LIMIT, setStorageInnerCalldata)
|
|
log.Debug("\n\nApplying `get()` SIMPLE STORAGE Tx to State.")
|
|
returnValue, _, _, _ := applyMessageToState(currentState, OTHER_FROM_ADDR, newContractAddr, GAS_LIMIT, getStorageInnerCalldata)
|
|
log.Debug("Complete.")
|
|
|
|
expectedReturnValue, _ := hex.DecodeString("0101010101010101010101010101010101010101010101010101010101010101")
|
|
if !bytes.Equal(returnValue[:], expectedReturnValue) {
|
|
t.Errorf("Expected %020x; got %020x", returnValue[:], expectedReturnValue)
|
|
}
|
|
}
|
|
|
|
func TestSloadAndStore(t *testing.T) {
|
|
rawStateManagerAbi, _ := ioutil.ReadFile("./StateManagerABI.json")
|
|
stateManagerAbi, _ := abi.JSON(strings.NewReader(string(rawStateManagerAbi)))
|
|
state := newState()
|
|
|
|
address := common.HexToAddress("9999999999999999999999999999999999999999")
|
|
key := [32]byte{}
|
|
value := [32]byte{}
|
|
copy(key[:], []byte("hello"))
|
|
copy(value[:], []byte("world"))
|
|
|
|
storeCalldata, _ := stateManagerAbi.Pack("setStorage", address, key, value)
|
|
getCalldata, _ := stateManagerAbi.Pack("getStorage", address, key)
|
|
|
|
call(t, state, vm.StateManagerAddress, storeCalldata)
|
|
getStorageReturnValue, _ := call(t, state, vm.StateManagerAddress, getCalldata)
|
|
|
|
if !bytes.Equal(value[:], getStorageReturnValue) {
|
|
t.Errorf("Expected %020x; got %020x", value[:], getStorageReturnValue)
|
|
}
|
|
}
|
|
|
|
func TestCreate(t *testing.T) {
|
|
currentState := newState()
|
|
initCode, _ := hex.DecodeString("608060405234801561001057600080fd5b5060405161026b38038061026b8339818101604052602081101561003357600080fd5b8101908080519060200190929190505050806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550506101d7806100946000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c80633408f73a1461003b578063d3404b6d14610045575b600080fd5b61004361004f565b005b61004d6100fa565b005b600060e060405180807f6f766d534c4f4144282900000000000000000000000000000000000000000000815250600a0190506040518091039020901c905060008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905060405136600082378260181c81538260101c60018201538260081c60028201538260038201536040516207a1208136846000875af160008114156100f657600080fd5b3d82f35b600060e060405180807f6f766d5353544f52452829000000000000000000000000000000000000000000815250600b0190506040518091039020901c905060008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905060405136600082378260181c81538260101c60018201538260081c600282015382600382015360008036836000865af1600081141561019c57600080fd5b5050505056fea265627a7a72315820311a406c97055eec367b660092882e1a174e14333416a3de384439293b7b129264736f6c6343000510003200000000000000000000000000000000000000000000000000000000dead0000")
|
|
applyMessageToState(currentState, OTHER_FROM_ADDR, ZERO_ADDRESS, GAS_LIMIT, initCode)
|
|
|
|
deployedBytecode := currentState.GetCode(crypto.CreateAddress(OTHER_FROM_ADDR, 0))
|
|
|
|
// Just make sure the deployed bytecode exists at that address
|
|
if len(deployedBytecode) == 0 {
|
|
t.Errorf("Deployed bytecode not found at expected address!")
|
|
}
|
|
}
|
|
|
|
func TestGetAndIncrementNonce(t *testing.T) {
|
|
rawStateManagerAbi, _ := ioutil.ReadFile("./StateManagerABI.json")
|
|
stateManagerAbi, _ := abi.JSON(strings.NewReader(string(rawStateManagerAbi)))
|
|
state := newState()
|
|
|
|
address := common.HexToAddress("9999999999999999999999999999999999999999")
|
|
|
|
getNonceCalldata, _ := stateManagerAbi.Pack("getOvmContractNonce", address)
|
|
incrementNonceCalldata, _ := stateManagerAbi.Pack("incrementOvmContractNonce", address)
|
|
|
|
getStorageReturnValue1, _ := call(t, state, vm.StateManagerAddress, getNonceCalldata)
|
|
|
|
expectedReturnValue1 := makeUint256WithUint64(0)
|
|
if !bytes.Equal(getStorageReturnValue1, expectedReturnValue1) {
|
|
t.Errorf("Expected %020x; got %020x", expectedReturnValue1, getStorageReturnValue1)
|
|
}
|
|
|
|
call(t, state, vm.StateManagerAddress, incrementNonceCalldata)
|
|
getStorageReturnValue2, _ := call(t, state, vm.StateManagerAddress, getNonceCalldata)
|
|
|
|
expectedReturnValue2 := makeUint256WithUint64(1)
|
|
if !bytes.Equal(getStorageReturnValue2, expectedReturnValue2) {
|
|
t.Errorf("Expected %020x; got %020x", expectedReturnValue2, getStorageReturnValue2)
|
|
}
|
|
}
|
|
|
|
func TestGetCodeContractAddressSucceedsForNormalContract(t *testing.T) {
|
|
rawStateManagerAbi, _ := ioutil.ReadFile("./StateManagerABI.json")
|
|
stateManagerAbi, _ := abi.JSON(strings.NewReader(string(rawStateManagerAbi)))
|
|
state := newState()
|
|
|
|
address := common.HexToAddress("9999999999999999999999999999999999999999")
|
|
|
|
getCodeContractAddressCalldata, _ := stateManagerAbi.Pack("getCodeContractAddressFromOvmAddress", address)
|
|
|
|
getCodeContractAddressReturnValue, _ := call(t, state, vm.StateManagerAddress, getCodeContractAddressCalldata)
|
|
|
|
if !bytes.Equal(getCodeContractAddressReturnValue[12:], address.Bytes()) {
|
|
t.Errorf("Expected %020x; got %020x", getCodeContractAddressReturnValue[12:], address.Bytes())
|
|
}
|
|
}
|
|
|
|
func TestGetCodeContractAddressFailsForDeadContract(t *testing.T) {
|
|
rawStateManagerAbi, _ := ioutil.ReadFile("./StateManagerABI.json")
|
|
stateManagerAbi, _ := abi.JSON(strings.NewReader(string(rawStateManagerAbi)))
|
|
state := newState()
|
|
|
|
deadAddress := common.HexToAddress("00000000000000000000000000000000dead9999")
|
|
|
|
getCodeContractAddressCalldata, _ := stateManagerAbi.Pack("getCodeContractAddressFromOvmAddress", deadAddress)
|
|
|
|
_, err := call(t, state, vm.StateManagerAddress, getCodeContractAddressCalldata)
|
|
|
|
if err == nil {
|
|
t.Errorf("Expected error to be thrown accessing dead address!")
|
|
}
|
|
}
|
|
|
|
func TestAssociateCodeContract(t *testing.T) {
|
|
rawStateManagerAbi, _ := ioutil.ReadFile("./StateManagerABI.json")
|
|
stateManagerAbi, _ := abi.JSON(strings.NewReader(string(rawStateManagerAbi)))
|
|
state := newState()
|
|
|
|
address := common.HexToAddress("9999999999999999999999999999999999999999")
|
|
|
|
getCodeContractAddressCalldata, _ := stateManagerAbi.Pack("associateCodeContract", address, address)
|
|
|
|
_, err := call(t, state, vm.StateManagerAddress, getCodeContractAddressCalldata)
|
|
if err != nil {
|
|
t.Errorf("Failed to call associateCodeContract: %s", err)
|
|
}
|
|
}
|
|
|
|
func TestGetCodeContractBytecode(t *testing.T) {
|
|
state := newState()
|
|
initCode, _ := hex.DecodeString("6080604052348015600f57600080fd5b5060b28061001e6000396000f3fe6080604052348015600f57600080fd5b506004361060285760003560e01c80639b0b0fda14602d575b600080fd5b606060048036036040811015604157600080fd5b8101908080359060200190929190803590602001909291905050506062565b005b8060008084815260200190815260200160002081905550505056fea265627a7a7231582053ac32a8b70d1cf87fb4ebf5a538ea9d9e773351e6c8afbc4bf6a6c273187f4a64736f6c63430005110032")
|
|
applyMessageToState(state, OTHER_FROM_ADDR, ZERO_ADDRESS, GAS_LIMIT, initCode)
|
|
|
|
deployedBytecode := state.GetCode(crypto.CreateAddress(OTHER_FROM_ADDR, 0))
|
|
expectedDeployedByteCode := common.FromHex("6080604052348015600f57600080fd5b506004361060285760003560e01c80639b0b0fda14602d575b600080fd5b606060048036036040811015604157600080fd5b8101908080359060200190929190803590602001909291905050506062565b005b8060008084815260200190815260200160002081905550505056fea265627a7a7231582053ac32a8b70d1cf87fb4ebf5a538ea9d9e773351e6c8afbc4bf6a6c273187f4a64736f6c63430005110032")
|
|
if !bytes.Equal(expectedDeployedByteCode, deployedBytecode) {
|
|
t.Errorf("Expected %020x; got %020x", expectedDeployedByteCode, deployedBytecode)
|
|
}
|
|
}
|
|
|
|
func TestGetCodeContractHash(t *testing.T) {
|
|
state := newState()
|
|
initCode, _ := hex.DecodeString("6080604052348015600f57600080fd5b5060b28061001e6000396000f3fe6080604052348015600f57600080fd5b506004361060285760003560e01c80639b0b0fda14602d575b600080fd5b606060048036036040811015604157600080fd5b8101908080359060200190929190803590602001909291905050506062565b005b8060008084815260200190815260200160002081905550505056fea265627a7a7231582053ac32a8b70d1cf87fb4ebf5a538ea9d9e773351e6c8afbc4bf6a6c273187f4a64736f6c63430005110032")
|
|
applyMessageToState(state, OTHER_FROM_ADDR, ZERO_ADDRESS, GAS_LIMIT, initCode)
|
|
|
|
rawStateManagerAbi, _ := ioutil.ReadFile("./StateManagerABI.json")
|
|
stateManagerAbi, _ := abi.JSON(strings.NewReader(string(rawStateManagerAbi)))
|
|
getCodeContractBytecodeCalldata, _ := stateManagerAbi.Pack("getCodeContractHash", crypto.CreateAddress(OTHER_FROM_ADDR, 0))
|
|
getCodeContractBytecodeReturnValue, _ := call(t, state, vm.StateManagerAddress, getCodeContractBytecodeCalldata)
|
|
expectedCreatedCodeHash := crypto.Keccak256(common.FromHex("6080604052348015600f57600080fd5b506004361060285760003560e01c80639b0b0fda14602d575b600080fd5b606060048036036040811015604157600080fd5b8101908080359060200190929190803590602001909291905050506062565b005b8060008084815260200190815260200160002081905550505056fea265627a7a7231582053ac32a8b70d1cf87fb4ebf5a538ea9d9e773351e6c8afbc4bf6a6c273187f4a64736f6c63430005110032"))
|
|
if !bytes.Equal(getCodeContractBytecodeReturnValue, expectedCreatedCodeHash) {
|
|
t.Errorf("Expected %020x; got %020x", getCodeContractBytecodeReturnValue, expectedCreatedCodeHash)
|
|
}
|
|
}
|
|
|
|
func makeUint256WithUint64(num uint64) []byte {
|
|
b := make([]byte, 8)
|
|
binary.BigEndian.PutUint64(b, num)
|
|
val := append(make([]byte, 24), b[:]...)
|
|
return val
|
|
}
|
|
|
|
func newState() *state.StateDB {
|
|
db := state.NewDatabase(rawdb.NewMemoryDatabase())
|
|
state, _ := state.New(common.Hash{}, db)
|
|
core.ApplyOvmStateToState(state)
|
|
return state
|
|
}
|
|
|
|
func applyMessageToState(currentState *state.StateDB, from common.Address, to common.Address, gasLimit uint64, data []byte) ([]byte, uint64, bool, error) {
|
|
header := &types.Header{
|
|
Number: big.NewInt(0),
|
|
Difficulty: big.NewInt(0),
|
|
Time: 1,
|
|
}
|
|
gasPool := core.GasPool(100000000)
|
|
// Generate the message
|
|
var message types.Message
|
|
if to == ZERO_ADDRESS {
|
|
// Check if to the ZERO_ADDRESS, if so, make it nil
|
|
message = types.NewMessage(
|
|
from,
|
|
nil,
|
|
currentState.GetNonce(from),
|
|
big.NewInt(0),
|
|
gasLimit,
|
|
big.NewInt(0),
|
|
data,
|
|
false,
|
|
&ZERO_ADDRESS,
|
|
nil,
|
|
)
|
|
} else {
|
|
// Otherwise we actually use the `to` field!
|
|
message = types.NewMessage(
|
|
from,
|
|
&to,
|
|
currentState.GetNonce(from),
|
|
big.NewInt(0),
|
|
gasLimit,
|
|
big.NewInt(0),
|
|
data,
|
|
false,
|
|
&ZERO_ADDRESS,
|
|
nil,
|
|
)
|
|
}
|
|
|
|
context := core.NewEVMContext(message, header, nil, &from)
|
|
evm := vm.NewEVM(context, currentState, &chainConfig, vm.Config{})
|
|
|
|
returnValue, gasUsed, failed, err := core.ApplyMessage(evm, message, &gasPool)
|
|
log.Debug("Return val: [HIDDEN]", "Gas used:", gasUsed, "Failed:", failed, "Error:", err)
|
|
|
|
commitHash, commitErr := currentState.Commit(false)
|
|
log.Debug("Commit hash:", commitHash, "Commit err:", commitErr)
|
|
|
|
return returnValue, gasUsed, failed, err
|
|
}
|
|
|
|
func call(t *testing.T, currentState *state.StateDB, address common.Address, callData []byte) ([]byte, error) {
|
|
returnValue, _, err := runtime.Call(address, callData, &runtime.Config{
|
|
State: currentState,
|
|
ChainConfig: &chainConfig,
|
|
})
|
|
|
|
return returnValue, err
|
|
}
|