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"
|
"github.com/filecoin-project/go-state-types/abi"
|
||||||
actorstypes "github.com/filecoin-project/go-state-types/actors"
|
actorstypes "github.com/filecoin-project/go-state-types/actors"
|
||||||
"github.com/filecoin-project/go-state-types/big"
|
"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/crypto"
|
||||||
"github.com/filecoin-project/go-state-types/manifest"
|
"github.com/filecoin-project/go-state-types/manifest"
|
||||||
"github.com/filecoin-project/go-state-types/network"
|
"github.com/filecoin-project/go-state-types/network"
|
||||||
@ -60,6 +59,8 @@ type GenesisBootstrap struct {
|
|||||||
Genesis *types.BlockHeader
|
Genesis *types.BlockHeader
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var EmptyObjCid = cid.Undef
|
||||||
|
|
||||||
/*
|
/*
|
||||||
From a list of parameters, create a genesis block / initial state
|
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) {
|
func MakeInitialStateTree(ctx context.Context, bs bstore.Blockstore, template genesis.Template) (*state.StateTree, map[address.Address]address.Address, error) {
|
||||||
// Create empty state tree
|
// Create empty state tree
|
||||||
|
|
||||||
cst := cbor.NewCborStore(bs)
|
cst := cbor.NewCborStore(bs)
|
||||||
_, err := cst.Put(context.TODO(), []struct{}{})
|
|
||||||
|
var err error
|
||||||
|
EmptyObjCid, err = cst.Put(context.TODO(), []struct{}{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, xerrors.Errorf("putting empty object: %w", err)
|
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
|
// Create accounts
|
||||||
for _, info := range template.Accounts {
|
for _, info := range template.Accounts {
|
||||||
|
|
||||||
switch info.Type {
|
switch info.Type {
|
||||||
case genesis.TAccount:
|
case genesis.TAccount:
|
||||||
if err := CreateAccountActor(ctx, cst, state, info, keyIDs, av); err != nil {
|
if err := CreateAccountActor(ctx, cst, state, info, keyIDs, av); err != nil {
|
||||||
return nil, nil, xerrors.Errorf("failed to create account actor: %w", err)
|
return nil, nil, xerrors.Errorf("failed to create account actor: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
case genesis.TMultisig:
|
case genesis.TMultisig:
|
||||||
|
|
||||||
ida, err := address.NewIDAddress(uint64(idStart))
|
ida, err := address.NewIDAddress(uint64(idStart))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
@ -592,10 +591,19 @@ func MakeGenesisBlock(ctx context.Context, j journal.Journal, bs bstore.Blocksto
|
|||||||
return nil, xerrors.Errorf("setup miners failed: %w", err)
|
return nil, xerrors.Errorf("setup miners failed: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// setup FEVM
|
st, err = state.LoadStateTree(st.Store, stateroot)
|
||||||
stateroot, err = SetupFEVM(ctx, cs, sys, stateroot, template.NetworkVersion)
|
|
||||||
if err != nil {
|
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))
|
store := adt.WrapStore(ctx, cbor.NewCborStore(bs))
|
||||||
@ -681,28 +689,3 @@ func MakeGenesisBlock(ctx context.Context, j journal.Journal, bs bstore.Blocksto
|
|||||||
Genesis: b,
|
Genesis: b,
|
||||||
}, nil
|
}, 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