Merge pull request #89 from filecoin-project/feat/chain-gen

Implement a chain generator
This commit is contained in:
Whyrusleeping 2019-07-29 09:57:40 -07:00 committed by GitHub
commit 508e19f52f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 224 additions and 42 deletions

146
chain/gen/gen.go Normal file
View File

@ -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
}

30
chain/gen/gen_test.go Normal file
View File

@ -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)
}

View File

@ -1,8 +1,7 @@
package chain package gen
import ( import (
"context" "context"
"fmt"
bls "github.com/filecoin-project/go-bls-sigs" bls "github.com/filecoin-project/go-bls-sigs"
cid "github.com/ipfs/go-cid" cid "github.com/ipfs/go-cid"
@ -17,10 +16,6 @@ import (
"github.com/filecoin-project/go-lotus/chain/vm" "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) { 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()) st, err := cs.TipSetState(parents.Cids())
if err != nil { if err != nil {
@ -29,13 +24,13 @@ func MinerCreateBlock(ctx context.Context, cs *store.ChainStore, miner address.A
height := parents.Height() + uint64(len(tickets)) 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 { if err != nil {
return nil, err return nil, err
} }
// apply miner reward // 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 return nil, err
} }
@ -46,7 +41,6 @@ func MinerCreateBlock(ctx context.Context, cs *store.ChainStore, miner address.A
Height: height, Height: height,
} }
fmt.Printf("adding %d messages to block...", len(msgs))
var msgCids []cid.Cid var msgCids []cid.Cid
var blsSigs []types.Signature var blsSigs []types.Signature
var receipts []interface{} var receipts []interface{}
@ -63,7 +57,7 @@ func MinerCreateBlock(ctx context.Context, cs *store.ChainStore, miner address.A
} else { } else {
msgCids = append(msgCids, msg.Cid()) msgCids = append(msgCids, msg.Cid())
} }
rec, err := vm.ApplyMessage(ctx, &msg.Message) rec, err := vmi.ApplyMessage(ctx, &msg.Message)
if err != nil { if err != nil {
return nil, errors.Wrap(err, "apply message failure") 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 next.MessageReceipts = rectroot
stateRoot, err := vm.Flush(context.TODO()) stateRoot, err := vmi.Flush(context.TODO())
if err != nil { if err != nil {
return nil, errors.Wrap(err, "flushing state tree failed") return nil, errors.Wrap(err, "flushing state tree failed")
} }

View File

@ -10,25 +10,11 @@ import (
"github.com/filecoin-project/go-lotus/chain/types" "github.com/filecoin-project/go-lotus/chain/types"
"github.com/ipfs/go-cid" "github.com/ipfs/go-cid"
dstore "github.com/ipfs/go-datastore"
hamt "github.com/ipfs/go-hamt-ipld" hamt "github.com/ipfs/go-hamt-ipld"
bstore "github.com/ipfs/go-ipfs-blockstore" bstore "github.com/ipfs/go-ipfs-blockstore"
sharray "github.com/whyrusleeping/sharray" 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 { type GenesisBootstrap struct {
Genesis *types.BlockHeader Genesis *types.BlockHeader
} }

View File

@ -526,18 +526,18 @@ func (syncer *Syncer) ValidateBlock(ctx context.Context, b *types.FullBlock) err
return 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 { if err != nil {
return err 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 return err
} }
var receipts []interface{} var receipts []interface{}
for _, m := range b.Messages { for _, m := range b.Messages {
receipt, err := vm.ApplyMessage(ctx, &m.Message) receipt, err := vmi.ApplyMessage(ctx, &m.Message)
if err != nil { if err != nil {
return err return err
} }
@ -554,7 +554,7 @@ func (syncer *Syncer) ValidateBlock(ctx context.Context, b *types.FullBlock) err
return fmt.Errorf("receipts mismatched") return fmt.Errorf("receipts mismatched")
} }
final, err := vm.Flush(context.TODO()) final, err := vmi.Flush(context.TODO())
if err != nil { if err != nil {
return err return err
} }

View File

@ -6,11 +6,27 @@ import (
"github.com/filecoin-project/go-lotus/chain/actors" "github.com/filecoin-project/go-lotus/chain/actors"
"github.com/filecoin-project/go-lotus/chain/address" "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/state"
"github.com/filecoin-project/go-lotus/chain/types" "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) { func TryCreateAccountActor(st *state.StateTree, addr address.Address) (*types.Actor, error) {
act, err := makeActor(st, addr) act, err := makeActor(st, addr)
if err != nil { if err != nil {
@ -62,7 +78,7 @@ func NewSecp256k1AccountActor(st *state.StateTree, addr address.Address) (*types
nact := &types.Actor{ nact := &types.Actor{
Code: actors.AccountActorCodeCid, Code: actors.AccountActorCodeCid,
Balance: types.NewInt(0), Balance: types.NewInt(0),
Head: gen.EmptyObjectCid, Head: EmptyObjectCid,
} }
return nact, nil return nact, nil

View File

@ -311,6 +311,9 @@ func Copy(ctx context.Context, from, to ipld.DAGService, root cid.Cid) error {
} }
links := node.Links() links := node.Links()
for _, link := range links { for _, link := range links {
if link.Cid.Prefix().MhType == 0 {
continue
}
_, err := to.Get(ctx, link.Cid) _, err := to.Get(ctx, link.Cid)
switch err { switch err {
default: default:
@ -381,3 +384,7 @@ func DeductFunds(act *types.Actor, amt types.BigInt) error {
func DepositFunds(act *types.Actor, amt types.BigInt) { func DepositFunds(act *types.Actor, amt types.BigInt) {
act.Balance = types.BigAdd(act.Balance, amt) act.Balance = types.BigAdd(act.Balance, amt)
} }
func MiningRewardForBlock(base *types.TipSet) types.BigInt {
return types.NewInt(10000)
}

View File

@ -1,4 +1,4 @@
package chain package wallet
import ( import (
"sort" "sort"

View File

@ -6,9 +6,9 @@ import (
"gopkg.in/urfave/cli.v2" "gopkg.in/urfave/cli.v2"
"github.com/filecoin-project/go-lotus/build" "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/actors"
"github.com/filecoin-project/go-lotus/chain/types" "github.com/filecoin-project/go-lotus/chain/types"
"github.com/filecoin-project/go-lotus/chain/wallet"
lcli "github.com/filecoin-project/go-lotus/cli" lcli "github.com/filecoin-project/go-lotus/cli"
"github.com/filecoin-project/go-lotus/node/repo" "github.com/filecoin-project/go-lotus/node/repo"
) )
@ -71,7 +71,7 @@ var initCmd = &cli.Command{
return err return err
} }
wallet, err := chain.NewWallet(ks) wallet, err := wallet.NewWallet(ks)
if err != nil { if err != nil {
return err return err
} }

View File

@ -26,6 +26,7 @@ import (
"github.com/filecoin-project/go-lotus/chain" "github.com/filecoin-project/go-lotus/chain"
"github.com/filecoin-project/go-lotus/chain/store" "github.com/filecoin-project/go-lotus/chain/store"
"github.com/filecoin-project/go-lotus/chain/types" "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/config"
"github.com/filecoin-project/go-lotus/node/hello" "github.com/filecoin-project/go-lotus/node/hello"
"github.com/filecoin-project/go-lotus/node/impl" "github.com/filecoin-project/go-lotus/node/impl"
@ -194,7 +195,7 @@ func Online() Option {
// Filecoin services // Filecoin services
Override(new(*chain.Syncer), chain.NewSyncer), Override(new(*chain.Syncer), chain.NewSyncer),
Override(new(*chain.BlockSync), chain.NewBlockSyncClient), 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(*chain.MessagePool), chain.NewMessagePool),
Override(new(modules.Genesis), modules.ErrorGenesis), Override(new(modules.Genesis), modules.ErrorGenesis),

View File

@ -8,8 +8,10 @@ import (
"github.com/filecoin-project/go-lotus/api" "github.com/filecoin-project/go-lotus/api"
"github.com/filecoin-project/go-lotus/chain" "github.com/filecoin-project/go-lotus/chain"
"github.com/filecoin-project/go-lotus/chain/address" "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/store"
"github.com/filecoin-project/go-lotus/chain/types" "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/miner"
"github.com/filecoin-project/go-lotus/node/client" "github.com/filecoin-project/go-lotus/node/client"
@ -28,7 +30,7 @@ type FullNodeAPI struct {
Chain *store.ChainStore Chain *store.ChainStore
PubSub *pubsub.PubSub PubSub *pubsub.PubSub
Mpool *chain.MessagePool Mpool *chain.MessagePool
Wallet *chain.Wallet Wallet *wallet.Wallet
} }
func (a *FullNodeAPI) ChainSubmitBlock(ctx context.Context, blk *chain.BlockMsg) error { 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) { 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 { if err != nil {
return nil, err return nil, err
} }

View File

@ -13,17 +13,17 @@ import (
logging "github.com/ipfs/go-log" logging "github.com/ipfs/go-log"
"github.com/ipfs/go-merkledag" "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/address"
"github.com/filecoin-project/go-lotus/chain/gen" "github.com/filecoin-project/go-lotus/chain/gen"
"github.com/filecoin-project/go-lotus/chain/types" "github.com/filecoin-project/go-lotus/chain/types"
"github.com/filecoin-project/go-lotus/chain/wallet"
"github.com/filecoin-project/go-lotus/node/modules" "github.com/filecoin-project/go-lotus/node/modules"
) )
var glog = logging.Logger("genesis") var glog = logging.Logger("genesis")
func MakeGenesisMem(out io.Writer) 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 *chain.Wallet) modules.Genesis { return func(bs blockstore.Blockstore, w *wallet.Wallet) 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")
// TODO: make an address allocation // 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 { func MakeGenesis(outFile string) func(bs blockstore.Blockstore, w *wallet.Wallet) modules.Genesis {
return func(bs blockstore.Blockstore, w *chain.Wallet) modules.Genesis { return func(bs blockstore.Blockstore, w *wallet.Wallet) 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")
minerAddr, err := w.GenerateKey(types.KTSecp256k1) minerAddr, err := w.GenerateKey(types.KTSecp256k1)