update genesis logic to create Eth Null Addresses as EthAccounts.
This commit is contained in:
parent
1e0c78098c
commit
d520dbbc4b
@ -1,113 +0,0 @@
|
||||
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/manifest"
|
||||
"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, manifest.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),
|
||||
}
|
||||
|
||||
if _, err := doExecValue(ctx, genesisVm, builtintypes.InitActorAddr, builtintypes.EthereumAddressManagerActorAddr, big.Zero(), builtintypes.MethodsInit.Exec4, 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
|
||||
|
||||
}
|
@ -16,7 +16,6 @@ import (
|
||||
"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"
|
||||
"github.com/filecoin-project/go-state-types/crypto"
|
||||
"github.com/filecoin-project/go-state-types/manifest"
|
||||
"github.com/filecoin-project/go-state-types/network"
|
||||
@ -60,6 +59,8 @@ type GenesisBootstrap struct {
|
||||
Genesis *types.BlockHeader
|
||||
}
|
||||
|
||||
var EmptyObjCid = cid.Undef
|
||||
|
||||
/*
|
||||
From a list of parameters, create a genesis block / initial state
|
||||
|
||||
@ -124,9 +125,10 @@ Genesis: {
|
||||
|
||||
func MakeInitialStateTree(ctx context.Context, bs bstore.Blockstore, template genesis.Template) (*state.StateTree, map[address.Address]address.Address, error) {
|
||||
// Create empty state tree
|
||||
|
||||
cst := cbor.NewCborStore(bs)
|
||||
_, err := cst.Put(context.TODO(), []struct{}{})
|
||||
|
||||
var err error
|
||||
EmptyObjCid, err = cst.Put(context.TODO(), []struct{}{})
|
||||
if err != nil {
|
||||
return nil, nil, xerrors.Errorf("putting empty object: %w", err)
|
||||
}
|
||||
@ -239,15 +241,12 @@ func MakeInitialStateTree(ctx context.Context, bs bstore.Blockstore, template ge
|
||||
|
||||
// Create accounts
|
||||
for _, info := range template.Accounts {
|
||||
|
||||
switch info.Type {
|
||||
case genesis.TAccount:
|
||||
if err := CreateAccountActor(ctx, cst, state, info, keyIDs, av); err != nil {
|
||||
return nil, nil, xerrors.Errorf("failed to create account actor: %w", err)
|
||||
}
|
||||
|
||||
case genesis.TMultisig:
|
||||
|
||||
ida, err := address.NewIDAddress(uint64(idStart))
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
@ -592,12 +591,21 @@ func MakeGenesisBlock(ctx context.Context, j journal.Journal, bs bstore.Blocksto
|
||||
return nil, xerrors.Errorf("setup miners failed: %w", err)
|
||||
}
|
||||
|
||||
// setup FEVM
|
||||
stateroot, err = SetupFEVM(ctx, cs, sys, stateroot, template.NetworkVersion)
|
||||
st, err = state.LoadStateTree(st.Store, stateroot)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("failed to setup FEVM functionality: %w", err)
|
||||
return nil, xerrors.Errorf("failed to load updated state tree: %w", err)
|
||||
}
|
||||
|
||||
// Set up Eth null addresses.
|
||||
if _, err := SetupEthNullAddresses(ctx, st, template.NetworkVersion); err != nil {
|
||||
return nil, xerrors.Errorf("failed to set up Eth null addresses: %w", err)
|
||||
}
|
||||
|
||||
stateroot, err = st.Flush(ctx)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("failed to flush state tree: %w", err)
|
||||
}
|
||||
|
||||
store := adt.WrapStore(ctx, cbor.NewCborStore(bs))
|
||||
emptyroot, err := adt0.MakeEmptyArray(store).Root()
|
||||
if err != nil {
|
||||
@ -681,28 +689,3 @@ func MakeGenesisBlock(ctx context.Context, j journal.Journal, bs bstore.Blocksto
|
||||
Genesis: b,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func SetupEAM(_ context.Context, nst *state.StateTree, nv network.Version) error {
|
||||
av, err := actorstypes.VersionForNetwork(nv)
|
||||
if err != nil {
|
||||
return 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 create.
|
||||
return nil
|
||||
}
|
||||
|
||||
codecid, ok := actors.GetActorCodeID(av, manifest.EamKey)
|
||||
if !ok {
|
||||
return fmt.Errorf("failed to get CodeCID for EAM during genesis")
|
||||
}
|
||||
|
||||
header := &types.Actor{
|
||||
Code: codecid,
|
||||
Head: vm.EmptyObjectCid,
|
||||
Balance: big.Zero(),
|
||||
Address: &builtintypes.EthereumAddressManagerActorAddr, // so that it can create ETH0
|
||||
}
|
||||
return nst.SetActor(builtintypes.EthereumAddressManagerActorAddr, header)
|
||||
}
|
||||
|
138
chain/gen/genesis/genesis_eth.go
Normal file
138
chain/gen/genesis/genesis_eth.go
Normal file
@ -0,0 +1,138 @@
|
||||
package genesis
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/filecoin-project/go-address"
|
||||
actorstypes "github.com/filecoin-project/go-state-types/actors"
|
||||
"github.com/filecoin-project/go-state-types/big"
|
||||
"github.com/filecoin-project/go-state-types/builtin"
|
||||
"github.com/filecoin-project/go-state-types/manifest"
|
||||
"github.com/filecoin-project/go-state-types/network"
|
||||
|
||||
"github.com/filecoin-project/lotus/chain/actors/adt"
|
||||
init_ "github.com/filecoin-project/lotus/chain/actors/builtin/init"
|
||||
"github.com/filecoin-project/lotus/chain/state"
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
"github.com/filecoin-project/lotus/chain/types/ethtypes"
|
||||
"golang.org/x/xerrors"
|
||||
|
||||
"github.com/filecoin-project/lotus/chain/actors"
|
||||
)
|
||||
|
||||
// EthNullAddresses are the Ethereum addresses we want to create zero-balanced EthAccounts in.
|
||||
// We may want to add null addresses for precompiles going forward.
|
||||
var EthNullAddresses = []string{
|
||||
"0x0000000000000000000000000000000000000000",
|
||||
}
|
||||
|
||||
func SetupEAM(_ context.Context, nst *state.StateTree, nv network.Version) error {
|
||||
av, err := actorstypes.VersionForNetwork(nv)
|
||||
if err != nil {
|
||||
return 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 create.
|
||||
return nil
|
||||
}
|
||||
|
||||
codecid, ok := actors.GetActorCodeID(av, manifest.EamKey)
|
||||
if !ok {
|
||||
return fmt.Errorf("failed to get CodeCID for EAM during genesis")
|
||||
}
|
||||
|
||||
header := &types.Actor{
|
||||
Code: codecid,
|
||||
Head: EmptyObjCid,
|
||||
Balance: big.Zero(),
|
||||
Address: &builtin.EthereumAddressManagerActorAddr, // so that it can create ETH0
|
||||
}
|
||||
return nst.SetActor(builtin.EthereumAddressManagerActorAddr, header)
|
||||
}
|
||||
|
||||
// MakeEthNullAddressActor creates a null address actor at the specified Ethereum address.
|
||||
func MakeEthNullAddressActor(av actorstypes.Version, addr address.Address) (*types.Actor, error) {
|
||||
actcid, ok := actors.GetActorCodeID(av, manifest.EthAccountKey)
|
||||
if !ok {
|
||||
return nil, xerrors.Errorf("failed to get account actor code ID for actors version %d", av)
|
||||
}
|
||||
|
||||
act := &types.Actor{
|
||||
Code: actcid,
|
||||
Head: EmptyObjCid,
|
||||
Nonce: 0,
|
||||
Balance: big.Zero(),
|
||||
Address: &addr,
|
||||
}
|
||||
|
||||
return act, nil
|
||||
}
|
||||
|
||||
func SetupEthNullAddresses(ctx context.Context, st *state.StateTree, nv network.Version) ([]address.Address, error) {
|
||||
av, err := actorstypes.VersionForNetwork(nv)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("failed to resolve actors version for network version %d: %w", err)
|
||||
}
|
||||
|
||||
if av < actorstypes.Version10 {
|
||||
// Not defined before version 10.
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
var ethAddresses []ethtypes.EthAddress
|
||||
for _, addr := range EthNullAddresses {
|
||||
a, err := ethtypes.EthAddressFromHex(addr)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("failed to represent the 0x0 as an EthAddress: %w", err)
|
||||
}
|
||||
ethAddresses = append(ethAddresses, a)
|
||||
}
|
||||
|
||||
initAct, err := st.GetActor(builtin.InitActorAddr)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("failed to load init actor: %w", err)
|
||||
}
|
||||
|
||||
initState, err := init_.Load(adt.WrapStore(ctx, st.Store), initAct)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("failed to load init actor state: %w", err)
|
||||
}
|
||||
|
||||
var ret []address.Address
|
||||
for _, ethAddr := range ethAddresses {
|
||||
// Place an EthAccount at the 0x0 Eth Null Address.
|
||||
f4Addr, err := ethAddr.ToFilecoinAddress()
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("failed to compute Filecoin address for Eth addr 0x0: %w", err)
|
||||
}
|
||||
|
||||
idAddr, err := initState.MapAddressToNewID(f4Addr)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("failed to map addr in init actor: %w", err)
|
||||
}
|
||||
|
||||
actState, err := MakeEthNullAddressActor(av, f4Addr)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("failed to create EthAccount actor for null address: %w", err)
|
||||
}
|
||||
|
||||
if err := st.SetActor(idAddr, actState); err != nil {
|
||||
return nil, xerrors.Errorf("failed to set Eth Null Address EthAccount actor state: %w", err)
|
||||
}
|
||||
|
||||
ret = append(ret, idAddr)
|
||||
}
|
||||
|
||||
initAct.Head, err = st.Store.Put(ctx, initState)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("failed to add init actor state to store: %w", err)
|
||||
}
|
||||
|
||||
if err := st.SetActor(builtin.InitActorAddr, initAct); err != nil {
|
||||
return nil, xerrors.Errorf("failed to set updated state for init actor: %w", err)
|
||||
}
|
||||
|
||||
return ret, nil
|
||||
}
|
Loading…
Reference in New Issue
Block a user