NV18: FEVM: setup FEVM during genesis: create ETH0 actor (#9664)
* setup FEVM during genesis: create ETH0 actor * make gen * doExec expects to,from not from, to * give EAM a predictable address * update go-state-types * proper constructor params * workaround the situation with empty contracts * put fevm construction after miner construction * lint * fix TestAPI itest off by 1, the new miner is not 1001 anymore; that's ETH0. * add itest for ETH0 setup * improve test: check eth0 address
This commit is contained in:
parent
7e759547bc
commit
5386bc2625
114
chain/gen/genesis/fevm.go
Normal file
114
chain/gen/genesis/fevm.go
Normal file
@ -0,0 +1,114 @@
|
||||
package genesis
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
|
||||
"github.com/ipfs/go-cid"
|
||||
|
||||
"github.com/filecoin-project/go-state-types/abi"
|
||||
actorstypes "github.com/filecoin-project/go-state-types/actors"
|
||||
"github.com/filecoin-project/go-state-types/big"
|
||||
builtintypes "github.com/filecoin-project/go-state-types/builtin"
|
||||
evm10 "github.com/filecoin-project/go-state-types/builtin/v10/evm"
|
||||
init10 "github.com/filecoin-project/go-state-types/builtin/v10/init"
|
||||
"github.com/filecoin-project/go-state-types/network"
|
||||
|
||||
"github.com/filecoin-project/lotus/chain/actors"
|
||||
"github.com/filecoin-project/lotus/chain/consensus/filcns"
|
||||
"github.com/filecoin-project/lotus/chain/state"
|
||||
"github.com/filecoin-project/lotus/chain/store"
|
||||
"github.com/filecoin-project/lotus/chain/vm"
|
||||
)
|
||||
|
||||
func SetupFEVM(ctx context.Context, cs *store.ChainStore, sys vm.SyscallBuilder, sroot cid.Cid, nv network.Version) (cid.Cid, error) {
|
||||
av, err := actorstypes.VersionForNetwork(nv)
|
||||
if err != nil {
|
||||
return cid.Undef, fmt.Errorf("failed to get actors version for network version %d: %w", nv, err)
|
||||
}
|
||||
|
||||
if av < actorstypes.Version10 {
|
||||
// Not defined before version 10; migration has to setup.
|
||||
return sroot, nil
|
||||
}
|
||||
|
||||
csc := func(context.Context, abi.ChainEpoch, *state.StateTree) (abi.TokenAmount, error) {
|
||||
return big.Zero(), nil
|
||||
}
|
||||
|
||||
newVM := func(base cid.Cid) (vm.Interface, error) {
|
||||
vmopt := &vm.VMOpts{
|
||||
StateBase: base,
|
||||
Epoch: 0,
|
||||
Rand: &fakeRand{},
|
||||
Bstore: cs.StateBlockstore(),
|
||||
Actors: filcns.NewActorRegistry(),
|
||||
Syscalls: mkFakedSigSyscalls(sys),
|
||||
CircSupplyCalc: csc,
|
||||
NetworkVersion: nv,
|
||||
BaseFee: big.Zero(),
|
||||
}
|
||||
|
||||
return vm.NewVM(ctx, vmopt)
|
||||
}
|
||||
|
||||
genesisVm, err := newVM(sroot)
|
||||
if err != nil {
|
||||
return cid.Undef, fmt.Errorf("creating vm: %w", err)
|
||||
}
|
||||
|
||||
// The ETH0 address is occupied by an empty contract EVM actor
|
||||
evmCodeCid, ok := actors.GetActorCodeID(av, actors.EvmKey)
|
||||
if !ok {
|
||||
return cid.Undef, fmt.Errorf("failed to get CodeCID for EVM during genesis")
|
||||
}
|
||||
|
||||
// initcode:
|
||||
// %push(code_end - code_begin)
|
||||
// dup1
|
||||
// %push(code_begin)
|
||||
// push1 0x00
|
||||
// codecopy
|
||||
// push1 0x00
|
||||
// return
|
||||
// code_begin:
|
||||
// push1 0x00
|
||||
// push1 0x00
|
||||
// return
|
||||
// code_end:
|
||||
initcode, err := hex.DecodeString("600580600b6000396000f360006000f3")
|
||||
if err != nil {
|
||||
return cid.Undef, fmt.Errorf("failed to parse ETH0 init code during genesis: %w", err)
|
||||
}
|
||||
|
||||
ctorParams := &evm10.ConstructorParams{
|
||||
Creator: make([]byte, 20), // self!
|
||||
// TODO we have a bunch of bugs in the evm constructor around empty contracts
|
||||
// - empty init code is not allowed
|
||||
// - returning an empty contract is not allowed
|
||||
// So this uses code that constructs a just return contract until that can be fixed
|
||||
// and we can pass an empty byte array
|
||||
Initcode: initcode,
|
||||
}
|
||||
|
||||
params := &init10.Exec4Params{
|
||||
CodeCID: evmCodeCid,
|
||||
ConstructorParams: mustEnc(ctorParams),
|
||||
SubAddress: make([]byte, 20),
|
||||
}
|
||||
|
||||
// TODO method 3 is Exec4; we have to name the methods in go-state-types and avoid using the number
|
||||
// directly.
|
||||
if _, err := doExecValue(ctx, genesisVm, builtintypes.InitActorAddr, builtintypes.EthereumAddressManagerActorAddr, big.Zero(), 3, mustEnc(params)); err != nil {
|
||||
return cid.Undef, fmt.Errorf("creating ETH0 actor: %w", err)
|
||||
}
|
||||
|
||||
newroot, err := genesisVm.Flush(ctx)
|
||||
if err != nil {
|
||||
return cid.Undef, fmt.Errorf("flushing vm: %w", err)
|
||||
}
|
||||
|
||||
return newroot, nil
|
||||
|
||||
}
|
@ -585,11 +585,18 @@ func MakeGenesisBlock(ctx context.Context, j journal.Journal, bs bstore.Blocksto
|
||||
return nil, xerrors.Errorf("failed to verify presealed data: %w", err)
|
||||
}
|
||||
|
||||
// setup Storage Miners
|
||||
stateroot, err = SetupStorageMiners(ctx, cs, sys, stateroot, template.Miners, template.NetworkVersion)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("setup miners failed: %w", err)
|
||||
}
|
||||
|
||||
// setup FEVM
|
||||
stateroot, err = SetupFEVM(ctx, cs, sys, stateroot, template.NetworkVersion)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("failed to setup FEVM functionality: %w", err)
|
||||
}
|
||||
|
||||
store := adt.WrapStore(ctx, cbor.NewCborStore(bs))
|
||||
emptyroot, err := adt0.MakeEmptyArray(store).Root()
|
||||
if err != nil {
|
||||
@ -694,6 +701,7 @@ func SetupEAM(_ context.Context, nst *state.StateTree, nv network.Version) error
|
||||
Code: codecid,
|
||||
Head: vm.EmptyObjectCid,
|
||||
Balance: big.Zero(),
|
||||
Address: &builtintypes.EthereumAddressManagerActorAddr, // so that it can create ETH0
|
||||
}
|
||||
return nst.SetActor(builtintypes.EthereumAddressManagerActorAddr, header)
|
||||
}
|
||||
|
2
go.mod
2
go.mod
@ -42,7 +42,7 @@ require (
|
||||
github.com/filecoin-project/go-legs v0.4.4
|
||||
github.com/filecoin-project/go-padreader v0.0.1
|
||||
github.com/filecoin-project/go-paramfetch v0.0.4
|
||||
github.com/filecoin-project/go-state-types v0.9.10-0.20221109071515-5536f160fe27
|
||||
github.com/filecoin-project/go-state-types v0.9.10-0.20221116204425-88b432576c58
|
||||
github.com/filecoin-project/go-statemachine v1.0.2
|
||||
github.com/filecoin-project/go-statestore v0.2.0
|
||||
github.com/filecoin-project/go-storedcounter v0.1.0
|
||||
|
4
go.sum
4
go.sum
@ -343,8 +343,8 @@ github.com/filecoin-project/go-state-types v0.1.0/go.mod h1:ezYnPf0bNkTsDibL/psS
|
||||
github.com/filecoin-project/go-state-types v0.1.6/go.mod h1:UwGVoMsULoCK+bWjEdd/xLCvLAQFBC7EDT477SKml+Q=
|
||||
github.com/filecoin-project/go-state-types v0.1.8/go.mod h1:UwGVoMsULoCK+bWjEdd/xLCvLAQFBC7EDT477SKml+Q=
|
||||
github.com/filecoin-project/go-state-types v0.1.10/go.mod h1:UwGVoMsULoCK+bWjEdd/xLCvLAQFBC7EDT477SKml+Q=
|
||||
github.com/filecoin-project/go-state-types v0.9.10-0.20221109071515-5536f160fe27 h1:1/o3al2zThas9rW6xqPKAzjs4q2tiBHaBNBP2sx0Vc4=
|
||||
github.com/filecoin-project/go-state-types v0.9.10-0.20221109071515-5536f160fe27/go.mod h1:7ty480tvttEAqWKywhAaDCElk7ksTqEXtXWAzTSdEKo=
|
||||
github.com/filecoin-project/go-state-types v0.9.10-0.20221116204425-88b432576c58 h1:yVk1uDtdOgcisfFT/Z9alb+M6LJKQci/Nw4zUPb5BLc=
|
||||
github.com/filecoin-project/go-state-types v0.9.10-0.20221116204425-88b432576c58/go.mod h1:7ty480tvttEAqWKywhAaDCElk7ksTqEXtXWAzTSdEKo=
|
||||
github.com/filecoin-project/go-statemachine v0.0.0-20200925024713-05bd7c71fbfe/go.mod h1:FGwQgZAt2Gh5mjlwJUlVB62JeYdo+if0xWxSEfBD9ig=
|
||||
github.com/filecoin-project/go-statemachine v1.0.2 h1:421SSWBk8GIoCoWYYTE/d+qCWccgmRH0uXotXRDjUbc=
|
||||
github.com/filecoin-project/go-statemachine v1.0.2/go.mod h1:jZdXXiHa61n4NmgWFG4w8tnqgvZVHYbJ3yW7+y8bF54=
|
||||
|
@ -307,5 +307,5 @@ func (ts *apiSuite) testNonGenesisMiner(t *testing.T) {
|
||||
tid, err := address.IDFromAddress(ta)
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Equal(t, uint64(1001), tid)
|
||||
require.Equal(t, uint64(1002), tid) // ETH0 is 1001
|
||||
}
|
||||
|
@ -12,7 +12,11 @@ import (
|
||||
cbg "github.com/whyrusleeping/cbor-gen"
|
||||
|
||||
"github.com/filecoin-project/go-address"
|
||||
actorstypes "github.com/filecoin-project/go-state-types/actors"
|
||||
builtintypes "github.com/filecoin-project/go-state-types/builtin"
|
||||
|
||||
"github.com/filecoin-project/lotus/chain/actors"
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
"github.com/filecoin-project/lotus/itests/kit"
|
||||
)
|
||||
|
||||
@ -86,3 +90,35 @@ func TestFEVMBasic(t *testing.T) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// TestFEVMETH0 tests that the ETH0 actor is in genesis
|
||||
func TestFEVMETH0(t *testing.T) {
|
||||
kit.QuietMiningLogs()
|
||||
|
||||
blockTime := 100 * time.Millisecond
|
||||
client, _, ens := kit.EnsembleMinimal(t, kit.MockProofs(), kit.ThroughRPC())
|
||||
ens.InterconnectAll().BeginMining(blockTime)
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), time.Minute)
|
||||
defer cancel()
|
||||
|
||||
eth0id, err := address.NewIDAddress(1001)
|
||||
require.NoError(t, err)
|
||||
|
||||
act, err := client.StateGetActor(ctx, eth0id, types.EmptyTSK)
|
||||
require.NoError(t, err)
|
||||
|
||||
nv, err := client.StateNetworkVersion(ctx, types.EmptyTSK)
|
||||
require.NoError(t, err)
|
||||
|
||||
av, err := actorstypes.VersionForNetwork(nv)
|
||||
require.NoError(t, err)
|
||||
|
||||
evmCodeCid, ok := actors.GetActorCodeID(av, actors.EvmKey)
|
||||
require.True(t, ok, "failed to get EVM code id")
|
||||
require.Equal(t, act.Code, evmCodeCid)
|
||||
|
||||
eth0Addr, err := address.NewDelegatedAddress(builtintypes.EthereumAddressManagerActorID, make([]byte, 20))
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, *act.Address, eth0Addr)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user