lotus/chain/gen/utils.go

190 lines
3.9 KiB
Go

package gen
import (
"context"
"fmt"
actors "github.com/filecoin-project/go-lotus/chain/actors"
"github.com/filecoin-project/go-lotus/chain/address"
"github.com/filecoin-project/go-lotus/chain/state"
"github.com/filecoin-project/go-lotus/chain/types"
"github.com/ipfs/go-cid"
hamt "github.com/ipfs/go-hamt-ipld"
bstore "github.com/ipfs/go-ipfs-blockstore"
sharray "github.com/whyrusleeping/sharray"
)
type GenesisBootstrap struct {
Genesis *types.BlockHeader
}
func SetupInitActor(bs bstore.Blockstore, addrs []address.Address) (*types.Actor, error) {
var ias actors.InitActorState
ias.NextID = 100
cst := hamt.CSTFromBstore(bs)
amap := hamt.NewNode(cst)
for i, a := range addrs {
if err := amap.Set(context.TODO(), string(a.Bytes()), 100+uint64(i)); err != nil {
return nil, err
}
}
ias.NextID += uint64(len(addrs))
if err := amap.Flush(context.TODO()); err != nil {
return nil, err
}
amapcid, err := cst.Put(context.TODO(), amap)
if err != nil {
return nil, err
}
ias.AddressMap = amapcid
statecid, err := cst.Put(context.TODO(), &ias)
if err != nil {
return nil, err
}
act := &types.Actor{
Code: actors.InitActorCodeCid,
Head: statecid,
}
return act, nil
}
func MakeInitialStateTree(bs bstore.Blockstore, actmap map[address.Address]types.BigInt) (*state.StateTree, error) {
cst := hamt.CSTFromBstore(bs)
state, err := state.NewStateTree(cst)
if err != nil {
return nil, err
}
emptyobject, err := cst.Put(context.TODO(), map[string]string{})
if err != nil {
return nil, err
}
var addrs []address.Address
for a := range actmap {
addrs = append(addrs, a)
}
initact, err := SetupInitActor(bs, addrs)
if err != nil {
return nil, err
}
if err := state.SetActor(actors.InitActorAddress, initact); err != nil {
return nil, err
}
smact, err := SetupStorageMarketActor(bs)
if err != nil {
return nil, err
}
if err := state.SetActor(actors.StorageMarketAddress, smact); err != nil {
return nil, err
}
err = state.SetActor(actors.NetworkAddress, &types.Actor{
Code: actors.AccountActorCodeCid,
Balance: types.NewInt(100000000000),
Head: emptyobject,
})
if err != nil {
return nil, err
}
for a, v := range actmap {
err = state.SetActor(a, &types.Actor{
Code: actors.AccountActorCodeCid,
Balance: v,
Head: emptyobject,
})
if err != nil {
return nil, err
}
}
return state, nil
}
func SetupStorageMarketActor(bs bstore.Blockstore) (*types.Actor, error) {
sms := &actors.StorageMarketState{
Miners: make(map[address.Address]struct{}),
TotalStorage: types.NewInt(0),
}
stcid, err := hamt.CSTFromBstore(bs).Put(context.TODO(), sms)
if err != nil {
return nil, err
}
return &types.Actor{
Code: actors.StorageMarketActorCodeCid,
Head: stcid,
Nonce: 0,
Balance: types.NewInt(0),
}, nil
}
func MakeGenesisBlock(bs bstore.Blockstore, balances map[address.Address]types.BigInt) (*GenesisBootstrap, error) {
fmt.Println("at end of make Genesis block")
state, err := MakeInitialStateTree(bs, balances)
if err != nil {
return nil, err
}
stateroot, err := state.Flush()
if err != nil {
return nil, err
}
cst := hamt.CSTFromBstore(bs)
emptyroot, err := sharray.Build(context.TODO(), 4, []interface{}{}, cst)
if err != nil {
return nil, err
}
mmcid, err := cst.Put(context.TODO(), &types.MsgMeta{
BlsMessages: emptyroot,
SecpkMessages: emptyroot,
})
if err != nil {
return nil, err
}
fmt.Println("Empty Genesis root: ", emptyroot)
b := &types.BlockHeader{
Miner: actors.InitActorAddress,
Tickets: []types.Ticket{},
ElectionProof: []byte("the Genesis block"),
Parents: []cid.Cid{},
Height: 0,
ParentWeight: types.NewInt(0),
StateRoot: stateroot,
Messages: mmcid,
MessageReceipts: emptyroot,
}
sb, err := b.ToStorageBlock()
if err != nil {
return nil, err
}
if err := bs.Put(sb); err != nil {
return nil, err
}
return &GenesisBootstrap{
Genesis: b,
}, nil
}