diff --git a/chain/gen/gen.go b/chain/gen/gen.go new file mode 100644 index 000000000..5d7b223ca --- /dev/null +++ b/chain/gen/gen.go @@ -0,0 +1,146 @@ +package gen + +import ( + "context" + + "github.com/filecoin-project/go-lotus/chain/address" + "github.com/filecoin-project/go-lotus/chain/store" + "github.com/filecoin-project/go-lotus/chain/types" + "github.com/filecoin-project/go-lotus/chain/wallet" + "github.com/filecoin-project/go-lotus/node/repo" + + block "github.com/ipfs/go-block-format" + "github.com/ipfs/go-cid" + blockstore "github.com/ipfs/go-ipfs-blockstore" + logging "github.com/ipfs/go-log" +) + +var log = logging.Logger("gen") + +type ChainGen struct { + accounts []address.Address + + msgsPerBlock int + + bs blockstore.Blockstore + + cs *store.ChainStore + + genesis *types.BlockHeader + + curBlock *types.FullBlock + + miner address.Address +} + +type mybs struct { + blockstore.Blockstore +} + +func (m mybs) Get(c cid.Cid) (block.Block, error) { + b, err := m.Blockstore.Get(c) + if err != nil { + log.Errorf("Get failed: %s %s", c, err) + return nil, err + } + + return b, nil +} + +func NewGenerator() (*ChainGen, error) { + + mr := repo.NewMemory(nil) + lr, err := mr.Lock() + if err != nil { + return nil, err + } + + ds, err := lr.Datastore("/blocks") + if err != nil { + return nil, err + } + bs := mybs{blockstore.NewBlockstore(ds)} + + ks, err := lr.KeyStore() + if err != nil { + return nil, err + } + + w, err := wallet.NewWallet(ks) + if err != nil { + return nil, err + } + + miner, err := w.GenerateKey(types.KTBLS) + if err != nil { + return nil, err + } + + banker, err := w.GenerateKey(types.KTBLS) + if err != nil { + return nil, err + } + + genb, err := MakeGenesisBlock(bs, map[address.Address]types.BigInt{ + banker: types.NewInt(90000000), + }) + if err != nil { + return nil, err + } + + cs := store.NewChainStore(bs, ds) + + msgsPerBlock := 10 + + genfb := &types.FullBlock{Header: genb.Genesis} + + if err := cs.SetGenesis(genb.Genesis); err != nil { + return nil, err + } + + gen := &ChainGen{ + bs: bs, + cs: cs, + msgsPerBlock: msgsPerBlock, + genesis: genb.Genesis, + miner: miner, + curBlock: genfb, + } + + return gen, nil +} + +func (cg *ChainGen) Genesis() *types.BlockHeader { + return cg.genesis +} + +func (cg *ChainGen) nextBlockProof() (address.Address, types.ElectionProof, []types.Ticket, error) { + return cg.miner, []byte("cat in a box"), []types.Ticket{types.Ticket("im a ticket, promise")}, nil +} + +func (cg *ChainGen) NextBlock() (*types.FullBlock, error) { + miner, proof, tickets, err := cg.nextBlockProof() + if err != nil { + return nil, err + } + + var msgs []*types.SignedMessage + + parents, err := types.NewTipSet([]*types.BlockHeader{cg.curBlock.Header}) + if err != nil { + return nil, err + } + + fblk, err := MinerCreateBlock(context.TODO(), cg.cs, miner, parents, tickets, proof, msgs) + if err != nil { + return nil, err + } + + if err := cg.cs.AddBlock(fblk.Header); err != nil { + return nil, err + } + + cg.curBlock = fblk + + return fblk, nil +} diff --git a/chain/gen/gen_test.go b/chain/gen/gen_test.go new file mode 100644 index 000000000..3fd8ec58b --- /dev/null +++ b/chain/gen/gen_test.go @@ -0,0 +1,30 @@ +package gen + +import ( + "testing" +) + +func testGeneration(t testing.TB, n int) { + g, err := NewGenerator() + if err != nil { + t.Fatal(err) + } + + for i := 0; i < n; i++ { + b, err := g.NextBlock() + if err != nil { + t.Fatalf("error at H:%d, %s", i, err) + } + if b.Header.Height != uint64(i+1) { + t.Fatal("wrong height") + } + } +} + +func TestChainGeneration(t *testing.T) { + testGeneration(t, 10) +} + +func BenchmarkChainGeneration(b *testing.B) { + testGeneration(b, b.N) +} diff --git a/chain/mining.go b/chain/gen/mining.go similarity index 87% rename from chain/mining.go rename to chain/gen/mining.go index ae4dc59a5..03e53e016 100644 --- a/chain/mining.go +++ b/chain/gen/mining.go @@ -1,8 +1,7 @@ -package chain +package gen import ( "context" - "fmt" bls "github.com/filecoin-project/go-bls-sigs" cid "github.com/ipfs/go-cid" @@ -17,10 +16,6 @@ import ( "github.com/filecoin-project/go-lotus/chain/vm" ) -func miningRewardForBlock(base *types.TipSet) types.BigInt { - return types.NewInt(10000) -} - func MinerCreateBlock(ctx context.Context, cs *store.ChainStore, miner address.Address, parents *types.TipSet, tickets []types.Ticket, proof types.ElectionProof, msgs []*types.SignedMessage) (*types.FullBlock, error) { st, err := cs.TipSetState(parents.Cids()) if err != nil { @@ -29,13 +24,13 @@ func MinerCreateBlock(ctx context.Context, cs *store.ChainStore, miner address.A height := parents.Height() + uint64(len(tickets)) - vm, err := vm.NewVM(st, height, miner, cs) + vmi, err := vm.NewVM(st, height, miner, cs) if err != nil { return nil, err } // apply miner reward - if err := vm.TransferFunds(actors.NetworkAddress, miner, miningRewardForBlock(parents)); err != nil { + if err := vmi.TransferFunds(actors.NetworkAddress, miner, vm.MiningRewardForBlock(parents)); err != nil { return nil, err } @@ -46,7 +41,6 @@ func MinerCreateBlock(ctx context.Context, cs *store.ChainStore, miner address.A Height: height, } - fmt.Printf("adding %d messages to block...", len(msgs)) var msgCids []cid.Cid var blsSigs []types.Signature var receipts []interface{} @@ -63,7 +57,7 @@ func MinerCreateBlock(ctx context.Context, cs *store.ChainStore, miner address.A } else { msgCids = append(msgCids, msg.Cid()) } - rec, err := vm.ApplyMessage(ctx, &msg.Message) + rec, err := vmi.ApplyMessage(ctx, &msg.Message) if err != nil { return nil, errors.Wrap(err, "apply message failure") } @@ -84,7 +78,7 @@ func MinerCreateBlock(ctx context.Context, cs *store.ChainStore, miner address.A } next.MessageReceipts = rectroot - stateRoot, err := vm.Flush(context.TODO()) + stateRoot, err := vmi.Flush(context.TODO()) if err != nil { return nil, errors.Wrap(err, "flushing state tree failed") } diff --git a/chain/gen/utils.go b/chain/gen/utils.go index 133ab7f61..a6454bd76 100644 --- a/chain/gen/utils.go +++ b/chain/gen/utils.go @@ -10,25 +10,11 @@ import ( "github.com/filecoin-project/go-lotus/chain/types" "github.com/ipfs/go-cid" - dstore "github.com/ipfs/go-datastore" hamt "github.com/ipfs/go-hamt-ipld" bstore "github.com/ipfs/go-ipfs-blockstore" sharray "github.com/whyrusleeping/sharray" ) -func init() { - bs := bstore.NewBlockstore(dstore.NewMapDatastore()) - cst := hamt.CSTFromBstore(bs) - emptyobject, err := cst.Put(context.TODO(), map[string]string{}) - if err != nil { - panic(err) - } - - EmptyObjectCid = emptyobject -} - -var EmptyObjectCid cid.Cid - type GenesisBootstrap struct { Genesis *types.BlockHeader } diff --git a/chain/sync.go b/chain/sync.go index dee9b84da..84837d471 100644 --- a/chain/sync.go +++ b/chain/sync.go @@ -526,18 +526,18 @@ func (syncer *Syncer) ValidateBlock(ctx context.Context, b *types.FullBlock) err return err } - vm, err := vm.NewVM(stateroot, b.Header.Height, b.Header.Miner, syncer.store) + vmi, err := vm.NewVM(stateroot, b.Header.Height, b.Header.Miner, syncer.store) if err != nil { return err } - if err := vm.TransferFunds(actors.NetworkAddress, b.Header.Miner, miningRewardForBlock(baseTs)); err != nil { + if err := vmi.TransferFunds(actors.NetworkAddress, b.Header.Miner, vm.MiningRewardForBlock(baseTs)); err != nil { return err } var receipts []interface{} for _, m := range b.Messages { - receipt, err := vm.ApplyMessage(ctx, &m.Message) + receipt, err := vmi.ApplyMessage(ctx, &m.Message) if err != nil { return err } @@ -554,7 +554,7 @@ func (syncer *Syncer) ValidateBlock(ctx context.Context, b *types.FullBlock) err return fmt.Errorf("receipts mismatched") } - final, err := vm.Flush(context.TODO()) + final, err := vmi.Flush(context.TODO()) if err != nil { return err } diff --git a/chain/vm/mkactor.go b/chain/vm/mkactor.go index 4ce8ff994..03dd31e64 100644 --- a/chain/vm/mkactor.go +++ b/chain/vm/mkactor.go @@ -6,11 +6,27 @@ import ( "github.com/filecoin-project/go-lotus/chain/actors" "github.com/filecoin-project/go-lotus/chain/address" - "github.com/filecoin-project/go-lotus/chain/gen" "github.com/filecoin-project/go-lotus/chain/state" "github.com/filecoin-project/go-lotus/chain/types" + "github.com/ipfs/go-cid" + dstore "github.com/ipfs/go-datastore" + hamt "github.com/ipfs/go-hamt-ipld" + bstore "github.com/ipfs/go-ipfs-blockstore" ) +func init() { + bs := bstore.NewBlockstore(dstore.NewMapDatastore()) + cst := hamt.CSTFromBstore(bs) + emptyobject, err := cst.Put(context.TODO(), map[string]string{}) + if err != nil { + panic(err) + } + + EmptyObjectCid = emptyobject +} + +var EmptyObjectCid cid.Cid + func TryCreateAccountActor(st *state.StateTree, addr address.Address) (*types.Actor, error) { act, err := makeActor(st, addr) if err != nil { @@ -62,7 +78,7 @@ func NewSecp256k1AccountActor(st *state.StateTree, addr address.Address) (*types nact := &types.Actor{ Code: actors.AccountActorCodeCid, Balance: types.NewInt(0), - Head: gen.EmptyObjectCid, + Head: EmptyObjectCid, } return nact, nil diff --git a/chain/vm/vm.go b/chain/vm/vm.go index f084aae9f..ec15e2db8 100644 --- a/chain/vm/vm.go +++ b/chain/vm/vm.go @@ -311,6 +311,9 @@ func Copy(ctx context.Context, from, to ipld.DAGService, root cid.Cid) error { } links := node.Links() for _, link := range links { + if link.Cid.Prefix().MhType == 0 { + continue + } _, err := to.Get(ctx, link.Cid) switch err { default: @@ -381,3 +384,7 @@ func DeductFunds(act *types.Actor, amt types.BigInt) error { func DepositFunds(act *types.Actor, amt types.BigInt) { act.Balance = types.BigAdd(act.Balance, amt) } + +func MiningRewardForBlock(base *types.TipSet) types.BigInt { + return types.NewInt(10000) +} diff --git a/chain/wallet.go b/chain/wallet/wallet.go similarity index 99% rename from chain/wallet.go rename to chain/wallet/wallet.go index accb4e1e6..c6cb3fc18 100644 --- a/chain/wallet.go +++ b/chain/wallet/wallet.go @@ -1,4 +1,4 @@ -package chain +package wallet import ( "sort" diff --git a/cmd/lotus-storage-miner/init.go b/cmd/lotus-storage-miner/init.go index 7402da672..fabd04fdc 100644 --- a/cmd/lotus-storage-miner/init.go +++ b/cmd/lotus-storage-miner/init.go @@ -6,9 +6,9 @@ import ( "gopkg.in/urfave/cli.v2" "github.com/filecoin-project/go-lotus/build" - "github.com/filecoin-project/go-lotus/chain" "github.com/filecoin-project/go-lotus/chain/actors" "github.com/filecoin-project/go-lotus/chain/types" + "github.com/filecoin-project/go-lotus/chain/wallet" lcli "github.com/filecoin-project/go-lotus/cli" "github.com/filecoin-project/go-lotus/node/repo" ) @@ -71,7 +71,7 @@ var initCmd = &cli.Command{ return err } - wallet, err := chain.NewWallet(ks) + wallet, err := wallet.NewWallet(ks) if err != nil { return err } diff --git a/node/builder.go b/node/builder.go index 17cd26a3f..0aa7a119b 100644 --- a/node/builder.go +++ b/node/builder.go @@ -26,6 +26,7 @@ import ( "github.com/filecoin-project/go-lotus/chain" "github.com/filecoin-project/go-lotus/chain/store" "github.com/filecoin-project/go-lotus/chain/types" + "github.com/filecoin-project/go-lotus/chain/wallet" "github.com/filecoin-project/go-lotus/node/config" "github.com/filecoin-project/go-lotus/node/hello" "github.com/filecoin-project/go-lotus/node/impl" @@ -194,7 +195,7 @@ func Online() Option { // Filecoin services Override(new(*chain.Syncer), chain.NewSyncer), Override(new(*chain.BlockSync), chain.NewBlockSyncClient), - Override(new(*chain.Wallet), chain.NewWallet), + Override(new(*wallet.Wallet), wallet.NewWallet), Override(new(*chain.MessagePool), chain.NewMessagePool), Override(new(modules.Genesis), modules.ErrorGenesis), diff --git a/node/impl/full.go b/node/impl/full.go index 8a467174f..c4643468d 100644 --- a/node/impl/full.go +++ b/node/impl/full.go @@ -8,8 +8,10 @@ import ( "github.com/filecoin-project/go-lotus/api" "github.com/filecoin-project/go-lotus/chain" "github.com/filecoin-project/go-lotus/chain/address" + "github.com/filecoin-project/go-lotus/chain/gen" "github.com/filecoin-project/go-lotus/chain/store" "github.com/filecoin-project/go-lotus/chain/types" + "github.com/filecoin-project/go-lotus/chain/wallet" "github.com/filecoin-project/go-lotus/miner" "github.com/filecoin-project/go-lotus/node/client" @@ -28,7 +30,7 @@ type FullNodeAPI struct { Chain *store.ChainStore PubSub *pubsub.PubSub Mpool *chain.MessagePool - Wallet *chain.Wallet + Wallet *wallet.Wallet } func (a *FullNodeAPI) ChainSubmitBlock(ctx context.Context, blk *chain.BlockMsg) error { @@ -100,7 +102,7 @@ func (a *FullNodeAPI) MinerStart(ctx context.Context, addr address.Address) erro } func (a *FullNodeAPI) MinerCreateBlock(ctx context.Context, addr address.Address, parents *types.TipSet, tickets []types.Ticket, proof types.ElectionProof, msgs []*types.SignedMessage) (*chain.BlockMsg, error) { - fblk, err := chain.MinerCreateBlock(ctx, a.Chain, addr, parents, tickets, proof, msgs) + fblk, err := gen.MinerCreateBlock(ctx, a.Chain, addr, parents, tickets, proof, msgs) if err != nil { return nil, err } diff --git a/node/modules/testing/genesis.go b/node/modules/testing/genesis.go index 3b9ce0e9c..7b923675b 100644 --- a/node/modules/testing/genesis.go +++ b/node/modules/testing/genesis.go @@ -13,17 +13,17 @@ import ( logging "github.com/ipfs/go-log" "github.com/ipfs/go-merkledag" - "github.com/filecoin-project/go-lotus/chain" "github.com/filecoin-project/go-lotus/chain/address" "github.com/filecoin-project/go-lotus/chain/gen" "github.com/filecoin-project/go-lotus/chain/types" + "github.com/filecoin-project/go-lotus/chain/wallet" "github.com/filecoin-project/go-lotus/node/modules" ) var glog = logging.Logger("genesis") -func MakeGenesisMem(out io.Writer) func(bs blockstore.Blockstore, w *chain.Wallet) modules.Genesis { - return func(bs blockstore.Blockstore, w *chain.Wallet) modules.Genesis { +func MakeGenesisMem(out io.Writer) func(bs blockstore.Blockstore, w *wallet.Wallet) modules.Genesis { + return func(bs blockstore.Blockstore, w *wallet.Wallet) modules.Genesis { 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") // TODO: make an address allocation @@ -44,8 +44,8 @@ func MakeGenesisMem(out io.Writer) func(bs blockstore.Blockstore, w *chain.Walle } } -func MakeGenesis(outFile string) func(bs blockstore.Blockstore, w *chain.Wallet) modules.Genesis { - return func(bs blockstore.Blockstore, w *chain.Wallet) modules.Genesis { +func MakeGenesis(outFile string) func(bs blockstore.Blockstore, w *wallet.Wallet) modules.Genesis { + return func(bs blockstore.Blockstore, w *wallet.Wallet) modules.Genesis { 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") minerAddr, err := w.GenerateKey(types.KTSecp256k1)