genesis: Cleanup the structure

This commit is contained in:
Łukasz Magiera 2020-02-11 21:48:03 +01:00
parent 3343e82307
commit 63e801e00f
21 changed files with 882 additions and 752 deletions

View File

@ -2,19 +2,19 @@ package actors
import ( import (
"github.com/filecoin-project/go-address" "github.com/filecoin-project/go-address"
"github.com/filecoin-project/specs-actors/actors/builtin"
"github.com/ipfs/go-cid" "github.com/ipfs/go-cid"
mh "github.com/multiformats/go-multihash"
) )
var AccountCodeCid cid.Cid var AccountCodeCid = builtin.AccountActorCodeID
var CronCodeCid cid.Cid var CronCodeCid = builtin.CronActorCodeID
var StoragePowerCodeCid cid.Cid var StoragePowerCodeCid = builtin.StoragePowerActorCodeID
var StorageMarketCodeCid cid.Cid var StorageMarketCodeCid = builtin.StorageMarketActorCodeID
var StorageMinerCodeCid cid.Cid var StorageMinerCodeCid = builtin.StorageMinerActorCodeID
var MultisigCodeCid cid.Cid var MultisigCodeCid = builtin.MultisigActorCodeID
var InitCodeCid cid.Cid var InitCodeCid = builtin.InitActorCodeID
var PaymentChannelCodeCid cid.Cid var PaymentChannelCodeCid = builtin.PaymentChannelActorCodeID
var SystemAddress = mustIDAddress(0) var SystemAddress = mustIDAddress(0)
var InitAddress = mustIDAddress(1) var InitAddress = mustIDAddress(1)
@ -36,24 +36,6 @@ func mustIDAddress(i uint64) address.Address {
} }
func init() { func init() {
pref := cid.NewPrefixV1(cid.Raw, mh.IDENTITY)
mustSum := func(s string) cid.Cid {
c, err := pref.Sum([]byte(s))
if err != nil {
panic(err) // ok
}
return c
}
AccountCodeCid = mustSum("fil/1/account") // TODO: spec
CronCodeCid = mustSum("fil/1/cron")
StoragePowerCodeCid = mustSum("fil/1/power")
StorageMarketCodeCid = mustSum("fil/1/market")
StorageMinerCodeCid = mustSum("fil/1/miner")
MultisigCodeCid = mustSum("fil/1/multisig")
InitCodeCid = mustSum("fil/1/init")
PaymentChannelCodeCid = mustSum("fil/1/paych")
BuiltInActors = map[cid.Cid]bool{ BuiltInActors = map[cid.Cid]bool{
StorageMarketCodeCid: true, StorageMarketCodeCid: true,
StoragePowerCodeCid: true, StoragePowerCodeCid: true,

View File

@ -7,15 +7,16 @@ import (
"testing" "testing"
"github.com/filecoin-project/lotus/build" "github.com/filecoin-project/lotus/build"
"github.com/filecoin-project/lotus/chain/gen/genesis"
"github.com/filecoin-project/go-address" "github.com/filecoin-project/go-address"
dstore "github.com/ipfs/go-datastore"
bstore "github.com/ipfs/go-ipfs-blockstore"
. "github.com/filecoin-project/lotus/chain/actors" . "github.com/filecoin-project/lotus/chain/actors"
"github.com/filecoin-project/lotus/chain/gen"
"github.com/filecoin-project/lotus/chain/store" "github.com/filecoin-project/lotus/chain/store"
"github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/chain/vm" "github.com/filecoin-project/lotus/chain/vm"
dstore "github.com/ipfs/go-datastore"
bstore "github.com/ipfs/go-ipfs-blockstore"
) )
func blsaddr(n uint64) address.Address { func blsaddr(n uint64) address.Address {
@ -40,7 +41,7 @@ func setupVMTestEnv(t *testing.T) (*vm.VM, []address.Address, bstore.Blockstore)
from: types.NewInt(1000000), from: types.NewInt(1000000),
maddr: types.NewInt(0), maddr: types.NewInt(0),
} }
st, err := gen.MakeInitialStateTree(bs, actors) st, err := genesis.MakeInitialStateTree(bs, actors)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }

View File

@ -19,8 +19,9 @@ import (
"golang.org/x/xerrors" "golang.org/x/xerrors"
"github.com/filecoin-project/go-address" "github.com/filecoin-project/go-address"
"github.com/filecoin-project/lotus/chain/actors" "github.com/filecoin-project/lotus/chain/actors"
"github.com/filecoin-project/lotus/chain/gen" "github.com/filecoin-project/lotus/chain/gen/genesis"
"github.com/filecoin-project/lotus/chain/state" "github.com/filecoin-project/lotus/chain/state"
"github.com/filecoin-project/lotus/chain/store" "github.com/filecoin-project/lotus/chain/store"
"github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/chain/types"
@ -183,7 +184,7 @@ func NewHarness(t *testing.T, options ...HarnessOpt) *Harness {
} }
} }
st, err := gen.MakeInitialStateTree(h.bs, h.HI.Addrs) st, err := genesis.MakeInitialStateTree(h.bs, h.HI.Addrs)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -193,7 +194,7 @@ func NewHarness(t *testing.T, options ...HarnessOpt) *Harness {
t.Fatal(err) t.Fatal(err)
} }
stateroot, err = gen.SetupStorageMarketActor(h.bs, stateroot, nil) stateroot, err = genesis.SetupStorageMarketActor(h.bs, stateroot, nil)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }

View File

@ -20,11 +20,13 @@ import (
"github.com/ipfs/go-merkledag" "github.com/ipfs/go-merkledag"
peer "github.com/libp2p/go-libp2p-core/peer" peer "github.com/libp2p/go-libp2p-core/peer"
ffi "github.com/filecoin-project/filecoin-ffi"
"github.com/filecoin-project/go-address" "github.com/filecoin-project/go-address"
sectorbuilder "github.com/filecoin-project/go-sectorbuilder" sectorbuilder "github.com/filecoin-project/go-sectorbuilder"
ffi "github.com/filecoin-project/filecoin-ffi"
"github.com/filecoin-project/lotus/api" "github.com/filecoin-project/lotus/api"
"github.com/filecoin-project/lotus/build" "github.com/filecoin-project/lotus/build"
genesis2 "github.com/filecoin-project/lotus/chain/gen/genesis"
"github.com/filecoin-project/lotus/chain/stmgr" "github.com/filecoin-project/lotus/chain/stmgr"
"github.com/filecoin-project/lotus/chain/store" "github.com/filecoin-project/lotus/chain/store"
"github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/chain/types"
@ -165,7 +167,7 @@ func NewGenerator() (*ChainGen, error) {
return nil, err return nil, err
} }
minercfg := &GenMinerCfg{ minercfg := &genesis2.GenMinerCfg{
PeerIDs: []peer.ID{"peerID1", "peerID2"}, PeerIDs: []peer.ID{"peerID1", "peerID2"},
PreSeals: map[string]genesis.GenesisMiner{ PreSeals: map[string]genesis.GenesisMiner{
maddr1.String(): *genm1, maddr1.String(): *genm1,
@ -176,7 +178,7 @@ func NewGenerator() (*ChainGen, error) {
sys := vm.Syscalls(sectorbuilder.ProofVerifier) sys := vm.Syscalls(sectorbuilder.ProofVerifier)
genb, err := MakeGenesisBlock(bs, sys, map[address.Address]types.BigInt{ genb, err := genesis2.MakeGenesisBlock(bs, sys, map[address.Address]types.BigInt{
mk1: types.FromFil(40000), mk1: types.FromFil(40000),
mk2: types.FromFil(40000), mk2: types.FromFil(40000),
banker: types.FromFil(50000), banker: types.FromFil(50000),

View File

@ -0,0 +1,195 @@
package genesis
import (
"context"
"github.com/filecoin-project/go-amt-ipld/v2"
"github.com/ipfs/go-cid"
"github.com/ipfs/go-datastore"
bstore "github.com/ipfs/go-ipfs-blockstore"
cbor "github.com/ipfs/go-ipld-cbor"
logging "github.com/ipfs/go-log/v2"
"golang.org/x/xerrors"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/lotus/build"
actors "github.com/filecoin-project/lotus/chain/actors"
"github.com/filecoin-project/lotus/chain/state"
"github.com/filecoin-project/lotus/chain/store"
"github.com/filecoin-project/lotus/chain/types"
)
var log = logging.Logger("genesis")
type GenesisBootstrap struct {
Genesis *types.BlockHeader
}
func MakeGenesisBlock(bs bstore.Blockstore, sys *types.VMSyscalls, balances map[address.Address]types.BigInt, gmcfg *GenMinerCfg, ts uint64) (*GenesisBootstrap, error) {
ctx := context.TODO()
state, err := MakeInitialStateTree(bs, balances)
if err != nil {
return nil, xerrors.Errorf("make initial state tree failed: %w", err)
}
stateroot, err := state.Flush(ctx)
if err != nil {
return nil, xerrors.Errorf("flush state tree failed: %w", err)
}
// temp chainstore
cs := store.NewChainStore(bs, datastore.NewMapDatastore(), sys)
stateroot, deals, err := SetupStorageMiners(ctx, cs, stateroot, gmcfg)
if err != nil {
return nil, xerrors.Errorf("setup storage miners failed: %w", err)
}
stateroot, err = SetupStorageMarketActor(bs, stateroot, deals)
if err != nil {
return nil, xerrors.Errorf("setup storage market actor: %w", err)
}
stateroot, err = AdjustInitActorStartID(ctx, bs, stateroot, 1000)
if err != nil {
return nil, xerrors.Errorf("failed to adjust init actor start ID: %w", err)
}
cst := cbor.NewCborStore(bs)
emptyroot, err := amt.FromArray(ctx, cst, nil)
if err != nil {
return nil, xerrors.Errorf("amt build failed: %w", err)
}
mm := &types.MsgMeta{
BlsMessages: emptyroot,
SecpkMessages: emptyroot,
}
mmb, err := mm.ToStorageBlock()
if err != nil {
return nil, xerrors.Errorf("serializing msgmeta failed: %w", err)
}
if err := bs.Put(mmb); err != nil {
return nil, xerrors.Errorf("putting msgmeta block to blockstore: %w", err)
}
log.Infof("Empty Genesis root: %s", emptyroot)
genesisticket := &types.Ticket{
VRFProof: []byte("vrf proof0000000vrf proof0000000"),
}
b := &types.BlockHeader{
Miner: actors.InitAddress,
Ticket: genesisticket,
EPostProof: types.EPostProof{
Proof: []byte("not a real proof"),
PostRand: []byte("i guess this is kinda random"),
},
Parents: []cid.Cid{},
Height: 0,
ParentWeight: types.NewInt(0),
ParentStateRoot: stateroot,
Messages: mmb.Cid(),
ParentMessageReceipts: emptyroot,
BLSAggregate: types.Signature{Type: types.KTBLS, Data: []byte("signatureeee")},
BlockSig: &types.Signature{Type: types.KTBLS, Data: []byte("block signatureeee")},
Timestamp: ts,
}
sb, err := b.ToStorageBlock()
if err != nil {
return nil, xerrors.Errorf("serializing block header failed: %w", err)
}
if err := bs.Put(sb); err != nil {
return nil, xerrors.Errorf("putting header to blockstore: %w", err)
}
return &GenesisBootstrap{
Genesis: b,
}, nil
}
func MakeInitialStateTree(bs bstore.Blockstore, actmap map[address.Address]types.BigInt) (*state.StateTree, error) {
cst := cbor.NewCborStore(bs)
state, err := state.NewStateTree(cst)
if err != nil {
return nil, xerrors.Errorf("making new state tree: %w", err)
}
emptyobject, err := cst.Put(context.TODO(), []struct{}{})
if err != nil {
return nil, xerrors.Errorf("failed putting empty object: %w", err)
}
var addrs []address.Address
for a := range actmap {
addrs = append(addrs, a)
}
initact, err := SetupInitActor(bs, addrs)
if err != nil {
return nil, xerrors.Errorf("setup init actor: %w", err)
}
if err := state.SetActor(actors.InitAddress, initact); err != nil {
return nil, xerrors.Errorf("set init actor: %w", err)
}
cronact, err := SetupCronActor(bs)
if err != nil {
return nil, xerrors.Errorf("setup cron actor: %w", err)
}
if err := state.SetActor(actors.CronAddress, cronact); err != nil {
return nil, xerrors.Errorf("set cron actor: %w", err)
}
spact, err := SetupStoragePowerActor(bs)
if err != nil {
return nil, xerrors.Errorf("setup storage market actor: %w", err)
}
if err := state.SetActor(actors.StoragePowerAddress, spact); err != nil {
return nil, xerrors.Errorf("set storage market actor: %w", err)
}
netAmt := types.FromFil(build.TotalFilecoin)
for _, amt := range actmap {
netAmt = types.BigSub(netAmt, amt)
}
err = state.SetActor(actors.NetworkAddress, &types.Actor{
Code: actors.AccountCodeCid,
Balance: netAmt,
Head: emptyobject,
})
if err != nil {
return nil, xerrors.Errorf("set network account actor: %w", err)
}
err = state.SetActor(actors.BurntFundsAddress, &types.Actor{
Code: actors.AccountCodeCid,
Balance: types.NewInt(0),
Head: emptyobject,
})
if err != nil {
return nil, xerrors.Errorf("set burnt funds account actor: %w", err)
}
for a, v := range actmap {
err = state.SetActor(a, &types.Actor{
Code: actors.AccountCodeCid,
Balance: v,
Head: emptyobject,
})
if err != nil {
return nil, xerrors.Errorf("setting account from actmap: %w", err)
}
}
return state, nil
}

203
chain/gen/genesis/miners.go Normal file
View File

@ -0,0 +1,203 @@
package genesis
import (
"bytes"
"context"
"github.com/filecoin-project/go-address"
commcid "github.com/filecoin-project/go-fil-commcid"
"github.com/filecoin-project/specs-actors/actors/abi"
"github.com/filecoin-project/specs-actors/actors/abi/big"
"github.com/filecoin-project/specs-actors/actors/builtin"
"github.com/filecoin-project/specs-actors/actors/builtin/miner"
"github.com/filecoin-project/specs-actors/actors/builtin/power"
"github.com/filecoin-project/specs-actors/actors/util/adt"
"github.com/ipfs/go-cid"
cbor "github.com/ipfs/go-ipld-cbor"
"github.com/libp2p/go-libp2p-core/peer"
"golang.org/x/xerrors"
"github.com/filecoin-project/lotus/chain/actors"
"github.com/filecoin-project/lotus/chain/store"
"github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/chain/vm"
"github.com/filecoin-project/lotus/genesis"
)
type GenMinerCfg struct {
PreSeals map[string]genesis.GenesisMiner
// The addresses of the created miner, this is set by the genesis setup
MinerAddrs []address.Address
PeerIDs []peer.ID
}
func SetupStorageMiners(ctx context.Context, cs *store.ChainStore, sroot cid.Cid, gmcfg *GenMinerCfg) (cid.Cid, []actors.StorageDealProposal, error) {
vm, err := vm.NewVM(sroot, 0, nil, actors.NetworkAddress, cs.Blockstore(), cs.VMSys())
if err != nil {
return cid.Undef, nil, xerrors.Errorf("failed to create NewVM: %w", err)
}
if len(gmcfg.MinerAddrs) == 0 {
return cid.Undef, nil, xerrors.New("no genesis miners")
}
if len(gmcfg.MinerAddrs) != len(gmcfg.PreSeals) {
return cid.Undef, nil, xerrors.Errorf("miner address list, and preseal count doesn't match (%d != %d)", len(gmcfg.MinerAddrs), len(gmcfg.PreSeals))
}
var deals []actors.StorageDealProposal
for i, maddr := range gmcfg.MinerAddrs {
ps, psok := gmcfg.PreSeals[maddr.String()]
if !psok {
return cid.Undef, nil, xerrors.Errorf("no preseal for miner %s", maddr)
}
minerParams := &miner.ConstructorParams{
OwnerAddr: ps.Owner,
WorkerAddr: ps.Worker,
SectorSize: ps.SectorSize,
PeerId: gmcfg.PeerIDs[i], // TODO: grab from preseal too
}
params := mustEnc(minerParams)
// TODO: hardcoding 6500 here is a little fragile, it changes any
// time anyone changes the initial account allocations
rval, err := doExecValue(ctx, vm, actors.StoragePowerAddress, ps.Worker, types.FromFil(6500), actors.SPAMethods.CreateMiner, params)
if err != nil {
return cid.Undef, nil, xerrors.Errorf("failed to create genesis miner: %w", err)
}
maddrret, err := address.NewFromBytes(rval)
if err != nil {
return cid.Undef, nil, err
}
_, err = vm.Flush(ctx)
if err != nil {
return cid.Undef, nil, err
}
cst := cbor.NewCborStore(cs.Blockstore())
if err := reassignMinerActorAddress(vm, cst, maddrret, maddr); err != nil {
return cid.Undef, nil, err
}
pledgeRequirements := make([]big.Int, len(ps.Sectors))
for i, sector := range ps.Sectors {
if sector.Deal.StartEpoch != 0 {
return cid.Undef, nil, xerrors.New("all deals must start at epoch 0")
}
dur := big.NewInt(int64(sector.Deal.Duration()))
siz := big.NewInt(int64(sector.Deal.PieceSize))
weight := big.Mul(dur, siz)
params = mustEnc(&power.OnSectorProveCommitParams{
Weight: power.SectorStorageWeightDesc{
SectorSize: ps.SectorSize,
Duration: sector.Deal.Duration(),
DealWeight: weight,
}})
ret, err := doExec(ctx, vm, actors.StoragePowerAddress, maddr, builtin.MethodsPower.OnSectorProveCommit, params)
if err != nil {
return cid.Undef, nil, xerrors.Errorf("failed to update total storage: %w", err)
}
if err := pledgeRequirements[i].UnmarshalCBOR(bytes.NewReader(ret)); err != nil {
return cid.Undef, nil, xerrors.Errorf("unmarshal pledge requirement: %w", err)
}
}
// we have to flush the vm here because it buffers stuff internally for perf reasons
if _, err := vm.Flush(ctx); err != nil {
return cid.Undef, nil, xerrors.Errorf("vm.Flush failed: %w", err)
}
st := vm.StateTree()
mact, err := st.GetActor(maddr)
if err != nil {
return cid.Undef, nil, xerrors.Errorf("get miner actor failed: %w", err)
}
var mstate miner.State
if err := cst.Get(ctx, mact.Head, &mstate); err != nil {
return cid.Undef, nil, xerrors.Errorf("getting miner actor state failed: %w", err)
}
for i, s := range ps.Sectors {
dur := big.NewInt(int64(s.Deal.Duration()))
siz := big.NewInt(int64(s.Deal.PieceSize))
weight := big.Mul(dur, siz)
oci := miner.SectorOnChainInfo{
Info: miner.SectorPreCommitInfo{
SectorNumber: s.SectorID,
SealedCID: commcid.ReplicaCommitmentV1ToCID(s.CommR[:]),
SealEpoch: 0,
DealIDs: []abi.DealID{abi.DealID(len(deals))},
Expiration: 0,
},
ActivationEpoch: s.Deal.StartEpoch,
DealWeight: weight,
PledgeRequirement: pledgeRequirements[i],
DeclaredFaultEpoch: -1,
DeclaredFaultDuration: -1,
}
nssroot := adt.AsArray(cs.Store(ctx), mstate.Sectors)
if err := nssroot.Set(uint64(s.SectorID), &oci); err != nil {
return cid.Cid{}, nil, xerrors.Errorf("add sector to set: %w", err)
}
mstate.Sectors = nssroot.Root()
mstate.ProvingSet = nssroot.Root()
deals = append(deals, s.Deal)
}
nstate, err := cst.Put(ctx, &mstate)
if err != nil {
return cid.Undef, nil, err
}
mact.Head = nstate
if err := st.SetActor(maddr, mact); err != nil {
return cid.Undef, nil, err
}
}
c, err := vm.Flush(ctx)
return c, deals, err
}
func reassignMinerActorAddress(vm *vm.VM, cst cbor.IpldStore, from, to address.Address) error {
if from == to {
return nil
}
act, err := vm.StateTree().GetActor(from)
if err != nil {
return xerrors.Errorf("reassign: failed to get 'from' actor: %w", err)
}
_, err = vm.StateTree().GetActor(to)
if err == nil {
return xerrors.Errorf("cannot reassign actor, target address taken")
}
if err := vm.StateTree().SetActor(to, act); err != nil {
return xerrors.Errorf("failed to reassign actor: %w", err)
}
// TODO: remove from
if err := adjustStoragePowerTracking(vm, cst, from, to); err != nil {
return xerrors.Errorf("adjusting storage market tracking: %w", err)
}
// Now, adjust the tracking in the init actor
return initActorReassign(vm, cst, from, to)
}

View File

@ -0,0 +1,164 @@
package genesis
import (
"bytes"
"context"
"github.com/filecoin-project/go-address"
"github.com/ipfs/go-cid"
"github.com/ipfs/go-hamt-ipld"
blockstore "github.com/ipfs/go-ipfs-blockstore"
bstore "github.com/ipfs/go-ipfs-blockstore"
cbor "github.com/ipfs/go-ipld-cbor"
cbg "github.com/whyrusleeping/cbor-gen"
"golang.org/x/xerrors"
"github.com/filecoin-project/lotus/chain/actors"
"github.com/filecoin-project/lotus/chain/state"
"github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/chain/vm"
)
func SetupInitActor(bs bstore.Blockstore, addrs []address.Address) (*types.Actor, error) {
var ias actors.InitActorState
ias.NextID = 100
cst := cbor.NewCborStore(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.InitCodeCid,
Head: statecid,
}
return act, nil
}
func AdjustInitActorStartID(ctx context.Context, bs blockstore.Blockstore, stateroot cid.Cid, val uint64) (cid.Cid, error) {
cst := cbor.NewCborStore(bs)
tree, err := state.LoadStateTree(cst, stateroot)
if err != nil {
return cid.Undef, err
}
act, err := tree.GetActor(actors.InitAddress)
if err != nil {
return cid.Undef, err
}
var st actors.InitActorState
if err := cst.Get(ctx, act.Head, &st); err != nil {
return cid.Undef, err
}
st.NextID = val
nstate, err := cst.Put(ctx, &st)
if err != nil {
return cid.Undef, err
}
act.Head = nstate
if err := tree.SetActor(actors.InitAddress, act); err != nil {
return cid.Undef, err
}
return tree.Flush(ctx)
}
func initActorReassign(vm *vm.VM, cst cbor.IpldStore, from, to address.Address) error {
ctx := context.TODO()
initact, err := vm.StateTree().GetActor(actors.InitAddress)
if err != nil {
return xerrors.Errorf("couldnt get init actor: %w", err)
}
var st actors.InitActorState
if err := cst.Get(ctx, initact.Head, &st); err != nil {
return xerrors.Errorf("reassign loading init actor state: %w", err)
}
amap, err := hamt.LoadNode(ctx, cst, st.AddressMap)
if err != nil {
return xerrors.Errorf("failed to load init actor map: %w", err)
}
target, err := address.IDFromAddress(from)
if err != nil {
return xerrors.Errorf("failed to extract ID: %w", err)
}
var out string
halt := xerrors.Errorf("halt")
err = amap.ForEach(ctx, func(k string, v interface{}) error {
_, val, err := cbg.CborReadHeader(bytes.NewReader(v.(*cbg.Deferred).Raw))
if err != nil {
return xerrors.Errorf("parsing int in map failed: %w", err)
}
if val == target {
out = k
return halt
}
return nil
})
if err == nil {
return xerrors.Errorf("could not find from address in init ID map")
}
if !xerrors.Is(err, halt) {
return xerrors.Errorf("finding address in ID map failed: %w", err)
}
if err := amap.Delete(ctx, out); err != nil {
return xerrors.Errorf("deleting 'from' entry in amap: %w", err)
}
if err := amap.Set(ctx, out, target); err != nil {
return xerrors.Errorf("setting 'to' entry in amap: %w", err)
}
if err := amap.Flush(ctx); err != nil {
return xerrors.Errorf("failed to flush amap: %w", err)
}
ncid, err := cst.Put(ctx, amap)
if err != nil {
return err
}
st.AddressMap = ncid
nacthead, err := cst.Put(ctx, &st)
if err != nil {
return err
}
initact.Head = nacthead
return nil
}

View File

@ -0,0 +1 @@
package genesis

View File

@ -0,0 +1,34 @@
package genesis
import (
"context"
"github.com/filecoin-project/specs-actors/actors/builtin"
"github.com/filecoin-project/specs-actors/actors/builtin/cron"
bstore "github.com/ipfs/go-ipfs-blockstore"
cbor "github.com/ipfs/go-ipld-cbor"
"github.com/filecoin-project/lotus/chain/actors"
"github.com/filecoin-project/lotus/chain/types"
)
func SetupCronActor(bs bstore.Blockstore) (*types.Actor, error) {
cst := cbor.NewCborStore(bs)
cas := &actors.CronActorState{Entries: []cron.Entry{{
Receiver: builtin.StoragePowerActorAddr,
MethodNum: builtin.MethodsPower.OnEpochTickEnd,
},
}}
stcid, err := cst.Put(context.TODO(), cas)
if err != nil {
return nil, err
}
return &types.Actor{
Code: actors.CronCodeCid,
Head: stcid,
Nonce: 0,
Balance: types.NewInt(0),
}, nil
}

View File

@ -0,0 +1,95 @@
package genesis
import (
"context"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/specs-actors/actors/abi/big"
"github.com/filecoin-project/specs-actors/actors/builtin/market"
"github.com/filecoin-project/specs-actors/actors/builtin/power"
"github.com/ipfs/go-hamt-ipld"
bstore "github.com/ipfs/go-ipfs-blockstore"
cbor "github.com/ipfs/go-ipld-cbor"
"golang.org/x/xerrors"
"github.com/filecoin-project/lotus/chain/actors"
"github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/chain/vm"
)
func SetupStoragePowerActor(bs bstore.Blockstore) (*types.Actor, error) {
ctx := context.TODO()
cst := cbor.NewCborStore(bs)
nd := hamt.NewNode(cst)
emptyhamt, err := cst.Put(ctx, nd)
if err != nil {
return nil, err
}
sms := &power.State{
TotalNetworkPower: big.Zero(),
MinerCount: 0,
EscrowTable: emptyhamt,
CronEventQueue: emptyhamt,
PoStDetectedFaultMiners: emptyhamt,
Claims: emptyhamt,
NumMinersMeetingMinPower: 0,
}
stcid, err := cst.Put(ctx, sms)
if err != nil {
return nil, err
}
return &types.Actor{
Code: actors.StoragePowerCodeCid,
Head: stcid,
Nonce: 0,
Balance: types.NewInt(0),
}, nil
}
func adjustStoragePowerTracking(vm *vm.VM, cst cbor.IpldStore, from, to address.Address) error {
ctx := context.TODO()
act, err := vm.StateTree().GetActor(actors.StoragePowerAddress)
if err != nil {
return xerrors.Errorf("loading storage power actor: %w", err)
}
var spst market.State
if err := cst.Get(ctx, act.Head, &spst); err != nil {
return xerrors.Errorf("loading storage power actor state: %w", err)
}
miners, err := hamt.LoadNode(ctx, cst, spst.Miners)
if err != nil {
return xerrors.Errorf("loading miner set: %w", err)
}
if err := miners.Delete(ctx, string(from.Bytes())); err != nil {
return xerrors.Errorf("deleting from spa set: %w", err)
}
if err := miners.Set(ctx, string(to.Bytes()), uint64(1)); err != nil {
return xerrors.Errorf("failed setting miner: %w", err)
}
if err := miners.Flush(ctx); err != nil {
return err
}
nminerscid, err := cst.Put(ctx, miners)
if err != nil {
return err
}
spst.Miners = nminerscid
nhead, err := cst.Put(ctx, &spst)
if err != nil {
return err
}
act.Head = nhead
return nil
}

View File

@ -0,0 +1,80 @@
package genesis
import (
"context"
"github.com/filecoin-project/go-amt-ipld/v2"
"github.com/filecoin-project/specs-actors/actors/builtin/market"
"github.com/ipfs/go-cid"
bstore "github.com/ipfs/go-ipfs-blockstore"
cbor "github.com/ipfs/go-ipld-cbor"
cbg "github.com/whyrusleeping/cbor-gen"
"golang.org/x/xerrors"
"github.com/filecoin-project/lotus/chain/actors"
"github.com/filecoin-project/lotus/chain/state"
"github.com/filecoin-project/lotus/chain/store"
"github.com/filecoin-project/lotus/chain/types"
)
func SetupStorageMarketActor(bs bstore.Blockstore, sroot cid.Cid, deals []market.DealProposal) (cid.Cid, error) {
ctx := context.TODO()
cst := cbor.NewCborStore(bs)
ast := store.ActorStore(context.TODO(), bs)
cdeals := make([]cbg.CBORMarshaler, len(deals))
sdeals := make([]cbg.CBORMarshaler, len(deals))
for i, deal := range deals {
d := deal // copy
cdeals[i] = &d
sdeals[i] = &market.DealState{
SectorStartEpoch: 1,
LastUpdatedEpoch: -1,
SlashEpoch: -1,
}
}
dealAmt, err := amt.FromArray(ctx, cst, cdeals)
if err != nil {
return cid.Undef, xerrors.Errorf("amt build failed: %w", err)
}
stateAmt, err := amt.FromArray(ctx, cst, sdeals)
if err != nil {
return cid.Undef, xerrors.Errorf("amt build failed: %w", err)
}
sms, err := market.ConstructState(ast)
if err != nil {
return cid.Cid{}, err
}
sms.Proposals = dealAmt
sms.States = stateAmt
stcid, err := cst.Put(context.TODO(), sms)
if err != nil {
return cid.Undef, err
}
// TODO: MARKET BALANCES!!!!!!111
act := &types.Actor{
Code: actors.StorageMarketCodeCid,
Head: stcid,
Nonce: 0,
Balance: types.NewInt(0),
}
state, err := state.LoadStateTree(cst, sroot)
if err != nil {
return cid.Undef, xerrors.Errorf("making new state tree: %w", err)
}
if err := state.SetActor(actors.StorageMarketAddress, act); err != nil {
return cid.Undef, xerrors.Errorf("set storage market actor: %w", err)
}
return state.Flush(context.TODO())
}

54
chain/gen/genesis/util.go Normal file
View File

@ -0,0 +1,54 @@
package genesis
import (
"context"
"fmt"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/specs-actors/actors/abi"
cbg "github.com/whyrusleeping/cbor-gen"
"golang.org/x/xerrors"
"github.com/filecoin-project/lotus/chain/actors"
"github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/chain/vm"
)
func mustEnc(i cbg.CBORMarshaler) []byte {
enc, err := actors.SerializeParams(i)
if err != nil {
panic(err) // ok
}
return enc
}
func doExec(ctx context.Context, vm *vm.VM, to, from address.Address, method abi.MethodNum, params []byte) ([]byte, error) {
return doExecValue(ctx, vm, to, from, types.NewInt(0), method, params)
}
func doExecValue(ctx context.Context, vm *vm.VM, to, from address.Address, value types.BigInt, method abi.MethodNum, params []byte) ([]byte, error) {
act, err := vm.StateTree().GetActor(from)
if err != nil {
return nil, xerrors.Errorf("doExec failed to get from actor: %w", err)
}
ret, err := vm.ApplyMessage(context.TODO(), &types.Message{
To: to,
From: from,
Method: method,
Params: params,
GasLimit: types.NewInt(1000000),
GasPrice: types.NewInt(0),
Value: value,
Nonce: act.Nonce,
})
if err != nil {
return nil, xerrors.Errorf("doExec apply message failed: %w", err)
}
if ret.ExitCode != 0 {
return nil, fmt.Errorf("failed to call method: %s", ret.ActorErr)
}
return ret.Return, nil
}

View File

@ -1,691 +0,0 @@
package gen
import (
"bytes"
"context"
"fmt"
amt "github.com/filecoin-project/go-amt-ipld/v2"
"github.com/filecoin-project/specs-actors/actors/abi"
"github.com/filecoin-project/specs-actors/actors/abi/big"
"github.com/filecoin-project/specs-actors/actors/builtin/market"
"github.com/filecoin-project/specs-actors/actors/builtin/miner"
"github.com/filecoin-project/specs-actors/actors/builtin/power"
"github.com/ipfs/go-cid"
"github.com/ipfs/go-datastore"
hamt "github.com/ipfs/go-hamt-ipld"
blockstore "github.com/ipfs/go-ipfs-blockstore"
bstore "github.com/ipfs/go-ipfs-blockstore"
cbor "github.com/ipfs/go-ipld-cbor"
peer "github.com/libp2p/go-libp2p-core/peer"
cbg "github.com/whyrusleeping/cbor-gen"
"golang.org/x/xerrors"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/lotus/build"
actors "github.com/filecoin-project/lotus/chain/actors"
"github.com/filecoin-project/lotus/chain/state"
"github.com/filecoin-project/lotus/chain/store"
"github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/chain/vm"
"github.com/filecoin-project/lotus/genesis"
)
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 := cbor.NewCborStore(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.InitCodeCid,
Head: statecid,
}
return act, nil
}
func MakeInitialStateTree(bs bstore.Blockstore, actmap map[address.Address]types.BigInt) (*state.StateTree, error) {
cst := cbor.NewCborStore(bs)
state, err := state.NewStateTree(cst)
if err != nil {
return nil, xerrors.Errorf("making new state tree: %w", err)
}
emptyobject, err := cst.Put(context.TODO(), map[string]string{})
if err != nil {
return nil, xerrors.Errorf("failed putting empty object: %w", err)
}
var addrs []address.Address
for a := range actmap {
addrs = append(addrs, a)
}
initact, err := SetupInitActor(bs, addrs)
if err != nil {
return nil, xerrors.Errorf("setup init actor: %w", err)
}
if err := state.SetActor(actors.InitAddress, initact); err != nil {
return nil, xerrors.Errorf("set init actor: %w", err)
}
cronact, err := SetupCronActor(bs)
if err != nil {
return nil, xerrors.Errorf("setup cron actor: %w", err)
}
if err := state.SetActor(actors.CronAddress, cronact); err != nil {
return nil, xerrors.Errorf("set cron actor: %w", err)
}
spact, err := SetupStoragePowerActor(bs)
if err != nil {
return nil, xerrors.Errorf("setup storage market actor: %w", err)
}
if err := state.SetActor(actors.StoragePowerAddress, spact); err != nil {
return nil, xerrors.Errorf("set storage market actor: %w", err)
}
netAmt := types.FromFil(build.TotalFilecoin)
for _, amt := range actmap {
netAmt = types.BigSub(netAmt, amt)
}
err = state.SetActor(actors.NetworkAddress, &types.Actor{
Code: actors.AccountCodeCid,
Balance: netAmt,
Head: emptyobject,
})
if err != nil {
return nil, xerrors.Errorf("set network account actor: %w", err)
}
err = state.SetActor(actors.BurntFundsAddress, &types.Actor{
Code: actors.AccountCodeCid,
Balance: types.NewInt(0),
Head: emptyobject,
})
if err != nil {
return nil, xerrors.Errorf("set burnt funds account actor: %w", err)
}
for a, v := range actmap {
err = state.SetActor(a, &types.Actor{
Code: actors.AccountCodeCid,
Balance: v,
Head: emptyobject,
})
if err != nil {
return nil, xerrors.Errorf("setting account from actmap: %w", err)
}
}
return state, nil
}
func SetupCronActor(bs bstore.Blockstore) (*types.Actor, error) {
cst := cbor.NewCborStore(bs)
cas := &actors.CronActorState{}
stcid, err := cst.Put(context.TODO(), cas)
if err != nil {
return nil, err
}
return &types.Actor{
Code: actors.CronCodeCid,
Head: stcid,
Nonce: 0,
Balance: types.NewInt(0),
}, nil
}
func SetupStoragePowerActor(bs bstore.Blockstore) (*types.Actor, error) {
ctx := context.TODO()
cst := cbor.NewCborStore(bs)
nd := hamt.NewNode(cst)
emptyhamt, err := cst.Put(ctx, nd)
if err != nil {
return nil, err
}
sms := &power.State{
TotalNetworkPower: big.Zero(),
MinerCount: 0,
EscrowTable: emptyhamt,
CronEventQueue: emptyhamt,
PoStDetectedFaultMiners: emptyhamt,
Claims: emptyhamt,
NumMinersMeetingMinPower: 0,
}
stcid, err := cst.Put(ctx, sms)
if err != nil {
return nil, err
}
return &types.Actor{
Code: actors.StoragePowerCodeCid,
Head: stcid,
Nonce: 0,
Balance: types.NewInt(0),
}, nil
}
func SetupStorageMarketActor(bs bstore.Blockstore, sroot cid.Cid, deals []actors.StorageDealProposal) (cid.Cid, error) {
ctx := context.TODO()
cst := cbor.NewCborStore(bs)
ast := store.ActorStore(context.TODO(), bs)
cdeals := make([]cbg.CBORMarshaler, len(deals))
sdeals := make([]cbg.CBORMarshaler, len(deals))
for i, deal := range deals {
cdeals[i] = &market.DealProposal{
PieceCID: deal.PieceCID,
PieceSize: deal.PieceSize,
Client: deal.Client,
Provider: deal.Provider,
StartEpoch: deal.StartEpoch,
EndEpoch: deal.EndEpoch,
StoragePricePerEpoch: deal.StoragePricePerEpoch,
ProviderCollateral: deal.ProviderCollateral,
ClientCollateral: deal.ClientCollateral,
}
sdeals[i] = &market.DealState{
SectorStartEpoch: 1,
LastUpdatedEpoch: -1,
SlashEpoch: -1,
}
}
dealAmt, err := amt.FromArray(ctx, cst, cdeals)
if err != nil {
return cid.Undef, xerrors.Errorf("amt build failed: %w", err)
}
stateAmt, err := amt.FromArray(ctx, cst, sdeals)
if err != nil {
return cid.Undef, xerrors.Errorf("amt build failed: %w", err)
}
sms, err := market.ConstructState(ast)
if err != nil {
return cid.Cid{}, err
}
sms.Proposals = dealAmt
sms.States = stateAmt
stcid, err := cst.Put(context.TODO(), sms)
if err != nil {
return cid.Undef, err
}
// TODO: MARKET BALANCES!!!!!!111
act := &types.Actor{
Code: actors.StorageMarketCodeCid,
Head: stcid,
Nonce: 0,
Balance: types.NewInt(0),
}
state, err := state.LoadStateTree(cst, sroot)
if err != nil {
return cid.Undef, xerrors.Errorf("making new state tree: %w", err)
}
if err := state.SetActor(actors.StorageMarketAddress, act); err != nil {
return cid.Undef, xerrors.Errorf("set storage market actor: %w", err)
}
return state.Flush(context.TODO())
}
type GenMinerCfg struct {
PreSeals map[string]genesis.GenesisMiner
// The addresses of the created miner, this is set by the genesis setup
MinerAddrs []address.Address
PeerIDs []peer.ID
}
func mustEnc(i cbg.CBORMarshaler) []byte {
enc, err := actors.SerializeParams(i)
if err != nil {
panic(err) // ok
}
return enc
}
func SetupStorageMiners(ctx context.Context, cs *store.ChainStore, sroot cid.Cid, gmcfg *GenMinerCfg) (cid.Cid, []actors.StorageDealProposal, error) {
vm, err := vm.NewVM(sroot, 0, nil, actors.NetworkAddress, cs.Blockstore(), cs.VMSys())
if err != nil {
return cid.Undef, nil, xerrors.Errorf("failed to create NewVM: %w", err)
}
if len(gmcfg.MinerAddrs) == 0 {
return cid.Undef, nil, xerrors.New("no genesis miners")
}
if len(gmcfg.MinerAddrs) != len(gmcfg.PreSeals) {
return cid.Undef, nil, xerrors.Errorf("miner address list, and preseal count doesn't match (%d != %d)", len(gmcfg.MinerAddrs), len(gmcfg.PreSeals))
}
var deals []actors.StorageDealProposal
for i, maddr := range gmcfg.MinerAddrs {
ps, psok := gmcfg.PreSeals[maddr.String()]
if !psok {
return cid.Undef, nil, xerrors.Errorf("no preseal for miner %s", maddr)
}
minerParams := &miner.ConstructorParams{
OwnerAddr: ps.Owner,
WorkerAddr: ps.Worker,
SectorSize: ps.SectorSize,
PeerId: gmcfg.PeerIDs[i], // TODO: grab from preseal too
}
params := mustEnc(minerParams)
// TODO: hardcoding 6500 here is a little fragile, it changes any
// time anyone changes the initial account allocations
rval, err := doExecValue(ctx, vm, actors.StoragePowerAddress, ps.Worker, types.FromFil(6500), actors.SPAMethods.CreateMiner, params)
if err != nil {
return cid.Undef, nil, xerrors.Errorf("failed to create genesis miner: %w", err)
}
maddrret, err := address.NewFromBytes(rval)
if err != nil {
return cid.Undef, nil, err
}
_, err = vm.Flush(ctx)
if err != nil {
return cid.Undef, nil, err
}
cst := cbor.NewCborStore(cs.Blockstore())
if err := reassignMinerActorAddress(vm, cst, maddrret, maddr); err != nil {
return cid.Undef, nil, err
}
power := types.BigMul(types.NewInt(uint64(minerParams.SectorSize)), types.NewInt(uint64(len(ps.Sectors))))
params = mustEnc(&actors.UpdateStorageParams{Delta: power})
_, err = doExec(ctx, vm, actors.StoragePowerAddress, maddr, actors.SPAMethods.UpdateStorage, params)
if err != nil {
return cid.Undef, nil, xerrors.Errorf("failed to update total storage: %w", err)
}
// we have to flush the vm here because it buffers stuff internally for perf reasons
if _, err := vm.Flush(ctx); err != nil {
return cid.Undef, nil, xerrors.Errorf("vm.Flush failed: %w", err)
}
st := vm.StateTree()
mact, err := st.GetActor(maddr)
if err != nil {
return cid.Undef, nil, xerrors.Errorf("get miner actor failed: %w", err)
}
var mstate actors.StorageMinerActorState
if err := cst.Get(ctx, mact.Head, &mstate); err != nil {
return cid.Undef, nil, xerrors.Errorf("getting miner actor state failed: %w", err)
}
mstate.Power = types.BigMul(types.NewInt(uint64(ps.SectorSize)), types.NewInt(uint64(len(ps.Sectors))))
for _, s := range ps.Sectors {
nssroot, err := actors.AddToSectorSet(ctx, cst, mstate.Sectors, s.SectorID, s.CommR[:], s.CommD[:])
if err != nil {
return cid.Undef, nil, xerrors.Errorf("failed to add fake sector to sector set: %w", err)
}
mstate.Sectors = nssroot
mstate.ProvingSet = nssroot
deals = append(deals, s.Deal)
}
nstate, err := cst.Put(ctx, &mstate)
if err != nil {
return cid.Undef, nil, err
}
mact.Head = nstate
if err := st.SetActor(maddr, mact); err != nil {
return cid.Undef, nil, err
}
}
c, err := vm.Flush(ctx)
return c, deals, err
}
func reassignMinerActorAddress(vm *vm.VM, cst cbor.IpldStore, from, to address.Address) error {
if from == to {
return nil
}
act, err := vm.StateTree().GetActor(from)
if err != nil {
return xerrors.Errorf("reassign: failed to get 'from' actor: %w", err)
}
_, err = vm.StateTree().GetActor(to)
if err == nil {
return xerrors.Errorf("cannot reassign actor, target address taken")
}
if err := vm.StateTree().SetActor(to, act); err != nil {
return xerrors.Errorf("failed to reassign actor: %w", err)
}
if err := adjustStorageMarketTracking(vm, cst, from, to); err != nil {
return xerrors.Errorf("adjusting storage market tracking: %w", err)
}
// Now, adjust the tracking in the init actor
return initActorReassign(vm, cst, from, to)
}
func adjustStorageMarketTracking(vm *vm.VM, cst cbor.IpldStore, from, to address.Address) error {
ctx := context.TODO()
act, err := vm.StateTree().GetActor(actors.StoragePowerAddress)
if err != nil {
return xerrors.Errorf("loading storage power actor: %w", err)
}
var spst actors.StoragePowerState
if err := cst.Get(ctx, act.Head, &spst); err != nil {
return xerrors.Errorf("loading storage power actor state: %w", err)
}
miners, err := hamt.LoadNode(ctx, cst, spst.Miners)
if err != nil {
return xerrors.Errorf("loading miner set: %w", err)
}
if err := miners.Delete(ctx, string(from.Bytes())); err != nil {
return xerrors.Errorf("deleting from spa set: %w", err)
}
if err := miners.Set(ctx, string(to.Bytes()), uint64(1)); err != nil {
return xerrors.Errorf("failed setting miner: %w", err)
}
if err := miners.Flush(ctx); err != nil {
return err
}
nminerscid, err := cst.Put(ctx, miners)
if err != nil {
return err
}
spst.Miners = nminerscid
nhead, err := cst.Put(ctx, &spst)
if err != nil {
return err
}
act.Head = nhead
return nil
}
func initActorReassign(vm *vm.VM, cst cbor.IpldStore, from, to address.Address) error {
ctx := context.TODO()
initact, err := vm.StateTree().GetActor(actors.InitAddress)
if err != nil {
return xerrors.Errorf("couldnt get init actor: %w", err)
}
var st actors.InitActorState
if err := cst.Get(ctx, initact.Head, &st); err != nil {
return xerrors.Errorf("reassign loading init actor state: %w", err)
}
amap, err := hamt.LoadNode(ctx, cst, st.AddressMap)
if err != nil {
return xerrors.Errorf("failed to load init actor map: %w", err)
}
target, err := address.IDFromAddress(from)
if err != nil {
return xerrors.Errorf("failed to extract ID: %w", err)
}
var out string
halt := xerrors.Errorf("halt")
err = amap.ForEach(ctx, func(k string, v interface{}) error {
_, val, err := cbg.CborReadHeader(bytes.NewReader(v.(*cbg.Deferred).Raw))
if err != nil {
return xerrors.Errorf("parsing int in map failed: %w", err)
}
if val == target {
out = k
return halt
}
return nil
})
if err == nil {
return xerrors.Errorf("could not find from address in init ID map")
}
if !xerrors.Is(err, halt) {
return xerrors.Errorf("finding address in ID map failed: %w", err)
}
if err := amap.Delete(ctx, out); err != nil {
return xerrors.Errorf("deleting 'from' entry in amap: %w", err)
}
if err := amap.Set(ctx, out, target); err != nil {
return xerrors.Errorf("setting 'to' entry in amap: %w", err)
}
if err := amap.Flush(ctx); err != nil {
return xerrors.Errorf("failed to flush amap: %w", err)
}
ncid, err := cst.Put(ctx, amap)
if err != nil {
return err
}
st.AddressMap = ncid
nacthead, err := cst.Put(ctx, &st)
if err != nil {
return err
}
initact.Head = nacthead
return nil
}
func doExec(ctx context.Context, vm *vm.VM, to, from address.Address, method uint64, params []byte) ([]byte, error) {
return doExecValue(ctx, vm, to, from, types.NewInt(0), method, params)
}
func doExecValue(ctx context.Context, vm *vm.VM, to, from address.Address, value types.BigInt, method abi.MethodNum, params []byte) ([]byte, error) {
act, err := vm.StateTree().GetActor(from)
if err != nil {
return nil, xerrors.Errorf("doExec failed to get from actor: %w", err)
}
ret, err := vm.ApplyMessage(context.TODO(), &types.Message{
To: to,
From: from,
Method: method,
Params: params,
GasLimit: types.NewInt(1000000),
GasPrice: types.NewInt(0),
Value: value,
Nonce: act.Nonce,
})
if err != nil {
return nil, xerrors.Errorf("doExec apply message failed: %w", err)
}
if ret.ExitCode != 0 {
return nil, fmt.Errorf("failed to call method: %s", ret.ActorErr)
}
return ret.Return, nil
}
func MakeGenesisBlock(bs bstore.Blockstore, sys *types.VMSyscalls, balances map[address.Address]types.BigInt, gmcfg *GenMinerCfg, ts uint64) (*GenesisBootstrap, error) {
ctx := context.TODO()
state, err := MakeInitialStateTree(bs, balances)
if err != nil {
return nil, xerrors.Errorf("make initial state tree failed: %w", err)
}
stateroot, err := state.Flush(ctx)
if err != nil {
return nil, xerrors.Errorf("flush state tree failed: %w", err)
}
// temp chainstore
cs := store.NewChainStore(bs, datastore.NewMapDatastore(), sys)
stateroot, deals, err := SetupStorageMiners(ctx, cs, stateroot, gmcfg)
if err != nil {
return nil, xerrors.Errorf("setup storage miners failed: %w", err)
}
stateroot, err = SetupStorageMarketActor(bs, stateroot, deals)
if err != nil {
return nil, xerrors.Errorf("setup storage market actor: %w", err)
}
stateroot, err = AdjustInitActorStartID(ctx, bs, stateroot, 1000)
if err != nil {
return nil, xerrors.Errorf("failed to adjust init actor start ID: %w", err)
}
cst := cbor.NewCborStore(bs)
emptyroot, err := amt.FromArray(ctx, cst, nil)
if err != nil {
return nil, xerrors.Errorf("amt build failed: %w", err)
}
mm := &types.MsgMeta{
BlsMessages: emptyroot,
SecpkMessages: emptyroot,
}
mmb, err := mm.ToStorageBlock()
if err != nil {
return nil, xerrors.Errorf("serializing msgmeta failed: %w", err)
}
if err := bs.Put(mmb); err != nil {
return nil, xerrors.Errorf("putting msgmeta block to blockstore: %w", err)
}
log.Infof("Empty Genesis root: %s", emptyroot)
genesisticket := &types.Ticket{
VRFProof: []byte("vrf proof0000000vrf proof0000000"),
}
b := &types.BlockHeader{
Miner: actors.InitAddress,
Ticket: genesisticket,
EPostProof: types.EPostProof{
Proof: []byte("not a real proof"),
PostRand: []byte("i guess this is kinda random"),
},
Parents: []cid.Cid{},
Height: 0,
ParentWeight: types.NewInt(0),
ParentStateRoot: stateroot,
Messages: mmb.Cid(),
ParentMessageReceipts: emptyroot,
BLSAggregate: types.Signature{Type: types.KTBLS, Data: []byte("signatureeee")},
BlockSig: &types.Signature{Type: types.KTBLS, Data: []byte("block signatureeee")},
Timestamp: ts,
}
sb, err := b.ToStorageBlock()
if err != nil {
return nil, xerrors.Errorf("serializing block header failed: %w", err)
}
if err := bs.Put(sb); err != nil {
return nil, xerrors.Errorf("putting header to blockstore: %w", err)
}
return &GenesisBootstrap{
Genesis: b,
}, nil
}
func AdjustInitActorStartID(ctx context.Context, bs blockstore.Blockstore, stateroot cid.Cid, val uint64) (cid.Cid, error) {
cst := cbor.NewCborStore(bs)
tree, err := state.LoadStateTree(cst, stateroot)
if err != nil {
return cid.Undef, err
}
act, err := tree.GetActor(actors.InitAddress)
if err != nil {
return cid.Undef, err
}
var st actors.InitActorState
if err := cst.Get(ctx, act.Head, &st); err != nil {
return cid.Undef, err
}
st.NextID = val
nstate, err := cst.Put(ctx, &st)
if err != nil {
return cid.Undef, err
}
act.Head = nstate
if err := tree.SetActor(actors.InitAddress, act); err != nil {
return cid.Undef, err
}
return tree.Flush(ctx)
}

View File

@ -20,8 +20,9 @@ import (
"github.com/filecoin-project/go-address" "github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-crypto" "github.com/filecoin-project/go-crypto"
"github.com/filecoin-project/lotus/chain/actors" "github.com/filecoin-project/lotus/chain/actors"
"github.com/filecoin-project/lotus/chain/gen" "github.com/filecoin-project/lotus/chain/gen/genesis"
"github.com/filecoin-project/lotus/chain/state" "github.com/filecoin-project/lotus/chain/state"
"github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/chain/vm" "github.com/filecoin-project/lotus/chain/vm"
@ -132,7 +133,7 @@ func (s *StateWrapper) SetSingletonActor(addr vactors.SingletonActorID, balance
switch lotusAddr { switch lotusAddr {
case actors.InitAddress: case actors.InitAddress:
initact, err := gen.SetupInitActor(s.bs, nil) initact, err := genesis.SetupInitActor(s.bs, nil)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -142,7 +143,7 @@ func (s *StateWrapper) SetSingletonActor(addr vactors.SingletonActorID, balance
return &actorWrapper{*initact}, s.storage, s.flush(tree) return &actorWrapper{*initact}, s.storage, s.flush(tree)
case actors.StorageMarketAddress: case actors.StorageMarketAddress:
nsroot, err := gen.SetupStorageMarketActor(s.bs, s.stateRoot, nil) nsroot, err := genesis.SetupStorageMarketActor(s.bs, s.stateRoot, nil)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -158,7 +159,7 @@ func (s *StateWrapper) SetSingletonActor(addr vactors.SingletonActorID, balance
} }
return &actorWrapper{*smact}, s.storage, s.flush(tree) return &actorWrapper{*smact}, s.storage, s.flush(tree)
case actors.StoragePowerAddress: case actors.StoragePowerAddress:
spact, err := gen.SetupStoragePowerActor(s.bs) spact, err := genesis.SetupStoragePowerActor(s.bs)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }

View File

@ -157,7 +157,7 @@ func createDeals(m *genesis.GenesisMiner, k *wallet.Key, maddr address.Address,
PieceSize: abi.PaddedPieceSize(ssize), PieceSize: abi.PaddedPieceSize(ssize),
Client: k.Address, Client: k.Address,
Provider: maddr, Provider: maddr,
StartEpoch: 1, // TODO: allow setting StartEpoch: 0,
EndEpoch: 9001, EndEpoch: 9001,
StoragePricePerEpoch: big.Zero(), StoragePricePerEpoch: big.Zero(),
ProviderCollateral: big.Zero(), ProviderCollateral: big.Zero(),

View File

@ -3,8 +3,8 @@ package genesis
import ( import (
"github.com/filecoin-project/go-address" "github.com/filecoin-project/go-address"
"github.com/filecoin-project/specs-actors/actors/abi" "github.com/filecoin-project/specs-actors/actors/abi"
"github.com/filecoin-project/specs-actors/actors/builtin/market"
"github.com/filecoin-project/lotus/chain/actors"
"github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/chain/types"
) )
@ -12,13 +12,17 @@ type PreSeal struct {
CommR [32]byte CommR [32]byte
CommD [32]byte CommD [32]byte
SectorID abi.SectorNumber SectorID abi.SectorNumber
Deal actors.StorageDealProposal Deal market.DealProposal
} }
type GenesisMiner struct { type GenesisMiner struct {
Owner address.Address Owner address.Address
Worker address.Address Worker address.Address
MarketBalance abi.TokenAmount
PowerBalance abi.TokenAmount
WorkerBalance abi.TokenAmount
SectorSize abi.SectorSize SectorSize abi.SectorSize
Sectors []*PreSeal Sectors []*PreSeal

View File

@ -20,7 +20,8 @@ import (
"golang.org/x/xerrors" "golang.org/x/xerrors"
"github.com/filecoin-project/go-address" "github.com/filecoin-project/go-address"
"github.com/filecoin-project/lotus/chain/gen"
genesis2 "github.com/filecoin-project/lotus/chain/gen/genesis"
"github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/chain/wallet" "github.com/filecoin-project/lotus/chain/wallet"
"github.com/filecoin-project/lotus/genesis" "github.com/filecoin-project/lotus/genesis"
@ -30,7 +31,7 @@ import (
var glog = logging.Logger("genesis") var glog = logging.Logger("genesis")
func MakeGenesisMem(out io.Writer, gmc *gen.GenMinerCfg) func(bs dtypes.ChainBlockstore, w *wallet.Wallet, syscalls *types.VMSyscalls) modules.Genesis { func MakeGenesisMem(out io.Writer, gmc *genesis2.GenMinerCfg) func(bs dtypes.ChainBlockstore, w *wallet.Wallet, syscalls *types.VMSyscalls) modules.Genesis {
return func(bs dtypes.ChainBlockstore, w *wallet.Wallet, syscalls *types.VMSyscalls) modules.Genesis { return func(bs dtypes.ChainBlockstore, w *wallet.Wallet, syscalls *types.VMSyscalls) modules.Genesis {
return func() (*types.BlockHeader, error) { return func() (*types.BlockHeader, error) {
glog.Warn("Generating new random genesis block, note that this SHOULD NOT happen unless you are setting up new network") glog.Warn("Generating new random genesis block, note that this SHOULD NOT happen unless you are setting up new network")
@ -51,7 +52,7 @@ func MakeGenesisMem(out io.Writer, gmc *gen.GenMinerCfg) func(bs dtypes.ChainBlo
alloc[waddr] = types.FromFil(10000) alloc[waddr] = types.FromFil(10000)
} }
b, err := gen.MakeGenesisBlock(bs, syscalls, alloc, gmc, 100000) b, err := genesis2.MakeGenesisBlock(bs, syscalls, alloc, gmc, 100000)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -101,7 +102,7 @@ func MakeGenesis(outFile, presealInfo, timestamp string) func(bs dtypes.ChainBlo
fakePeerIDs = append(fakePeerIDs, peer.ID("peer"+a.String())) fakePeerIDs = append(fakePeerIDs, peer.ID("peer"+a.String()))
} }
gmc := &gen.GenMinerCfg{ gmc := &genesis2.GenMinerCfg{
PeerIDs: fakePeerIDs, PeerIDs: fakePeerIDs,
PreSeals: preseals, PreSeals: preseals,
MinerAddrs: minerAddresses, MinerAddrs: minerAddresses,
@ -130,7 +131,7 @@ func MakeGenesis(outFile, presealInfo, timestamp string) func(bs dtypes.ChainBlo
ts = uint64(t.Unix()) ts = uint64(t.Unix())
} }
b, err := gen.MakeGenesisBlock(bs, syscalls, addrs, gmc, ts) b, err := genesis2.MakeGenesisBlock(bs, syscalls, addrs, gmc, ts)
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@ -12,7 +12,10 @@ import (
"github.com/filecoin-project/go-address" "github.com/filecoin-project/go-address"
sectorbuilder "github.com/filecoin-project/go-sectorbuilder" sectorbuilder "github.com/filecoin-project/go-sectorbuilder"
"github.com/filecoin-project/lotus/build" "github.com/filecoin-project/lotus/build"
genesis2 "github.com/filecoin-project/lotus/chain/gen/genesis"
"github.com/filecoin-project/specs-actors/actors/abi" "github.com/filecoin-project/specs-actors/actors/abi"
"github.com/ipfs/go-datastore" "github.com/ipfs/go-datastore"
"github.com/ipfs/go-datastore/namespace" "github.com/ipfs/go-datastore/namespace"
@ -27,7 +30,6 @@ import (
"github.com/filecoin-project/lotus/api/client" "github.com/filecoin-project/lotus/api/client"
"github.com/filecoin-project/lotus/api/test" "github.com/filecoin-project/lotus/api/test"
"github.com/filecoin-project/lotus/chain/actors" "github.com/filecoin-project/lotus/chain/actors"
"github.com/filecoin-project/lotus/chain/gen"
"github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/cmd/lotus-seed/seed" "github.com/filecoin-project/lotus/cmd/lotus-seed/seed"
"github.com/filecoin-project/lotus/genesis" "github.com/filecoin-project/lotus/genesis"
@ -153,7 +155,7 @@ func builder(t *testing.T, nFull int, storage []int) ([]test.TestNode, []test.Te
} }
// PRESEAL SECTION, TRY TO REPLACE WITH BETTER IN THE FUTURE // PRESEAL SECTION, TRY TO REPLACE WITH BETTER IN THE FUTURE
// TODO: would be great if there was a better way to fake the preseals // TODO: would be great if there was a better way to fake the preseals
gmc := &gen.GenMinerCfg{ gmc := &genesis2.GenMinerCfg{
PeerIDs: []peer.ID{minerPid}, // TODO: if we have more miners, need more peer IDs PeerIDs: []peer.ID{minerPid}, // TODO: if we have more miners, need more peer IDs
PreSeals: map[string]genesis.GenesisMiner{}, PreSeals: map[string]genesis.GenesisMiner{},
} }
@ -272,7 +274,7 @@ func mockSbBuilder(t *testing.T, nFull int, storage []int) ([]test.TestNode, []t
} }
// PRESEAL SECTION, TRY TO REPLACE WITH BETTER IN THE FUTURE // PRESEAL SECTION, TRY TO REPLACE WITH BETTER IN THE FUTURE
// TODO: would be great if there was a better way to fake the preseals // TODO: would be great if there was a better way to fake the preseals
gmc := &gen.GenMinerCfg{ gmc := &genesis2.GenMinerCfg{
PeerIDs: []peer.ID{minerPid}, // TODO: if we have more miners, need more peer IDs PeerIDs: []peer.ID{minerPid}, // TODO: if we have more miners, need more peer IDs
PreSeals: map[string]genesis.GenesisMiner{}, PreSeals: map[string]genesis.GenesisMiner{},
} }

View File

@ -10,6 +10,7 @@ import (
commcid "github.com/filecoin-project/go-fil-commcid" commcid "github.com/filecoin-project/go-fil-commcid"
"github.com/filecoin-project/specs-actors/actors/abi" "github.com/filecoin-project/specs-actors/actors/abi"
"github.com/filecoin-project/specs-actors/actors/builtin"
"github.com/filecoin-project/specs-actors/actors/builtin/market" "github.com/filecoin-project/specs-actors/actors/builtin/market"
"golang.org/x/xerrors" "golang.org/x/xerrors"
@ -65,7 +66,7 @@ func (m *Sealing) pledgeSector(ctx context.Context, sectorID abi.SectorNumber, e
log.Infof("Publishing deals for %d", sectorID) log.Infof("Publishing deals for %d", sectorID)
params, aerr := actors.SerializeParams(&actors.PublishStorageDealsParams{ params, aerr := actors.SerializeParams(&market.PublishStorageDealsParams{
Deals: deals, Deals: deals,
}) })
if aerr != nil { if aerr != nil {
@ -78,7 +79,7 @@ func (m *Sealing) pledgeSector(ctx context.Context, sectorID abi.SectorNumber, e
Value: types.NewInt(0), Value: types.NewInt(0),
GasPrice: types.NewInt(0), GasPrice: types.NewInt(0),
GasLimit: types.NewInt(1000000), GasLimit: types.NewInt(1000000),
Method: actors.SMAMethods.PublishStorageDeals, Method: builtin.MethodsMarket.PublishStorageDeals,
Params: params, Params: params,
}) })
if err != nil { if err != nil {