140 lines
4.3 KiB
Go
140 lines
4.3 KiB
Go
|
package genesis
|
||
|
|
||
|
import (
|
||
|
"context"
|
||
|
"fmt"
|
||
|
|
||
|
"golang.org/x/xerrors"
|
||
|
|
||
|
"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"
|
||
|
"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"
|
||
|
"github.com/filecoin-project/lotus/chain/vm"
|
||
|
)
|
||
|
|
||
|
// 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: vm.EmptyObjectCid,
|
||
|
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 EthAccount actor code ID for actors version %d", av)
|
||
|
}
|
||
|
|
||
|
act := &types.Actor{
|
||
|
Code: actcid,
|
||
|
Head: vm.EmptyObjectCid,
|
||
|
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", av, err)
|
||
|
}
|
||
|
|
||
|
if av < actorstypes.Version10 {
|
||
|
// Not defined before version 10.
|
||
|
return nil, nil
|
||
|
}
|
||
|
|
||
|
var ethAddresses []ethtypes.EthAddress
|
||
|
for _, addr := range EthNullAddresses {
|
||
|
a, err := ethtypes.ParseEthAddress(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
|
||
|
}
|