Merge pull request #89 from filecoin-project/feat/chain-gen
Implement a chain generator
This commit is contained in:
commit
508e19f52f
146
chain/gen/gen.go
Normal file
146
chain/gen/gen.go
Normal 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
30
chain/gen/gen_test.go
Normal 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)
|
||||
}
|
@ -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")
|
||||
}
|
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
package chain
|
||||
package wallet
|
||||
|
||||
import (
|
||||
"sort"
|
@ -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
|
||||
}
|
||||
|
@ -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),
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user