Merge pull request #243 from filecoin-project/feat/tipset-state-refactor
switch to parent state roots
This commit is contained in:
commit
557dfd3703
@ -191,7 +191,6 @@ type DealInfo struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type MsgWait struct {
|
type MsgWait struct {
|
||||||
InBlock cid.Cid
|
|
||||||
Receipt types.MessageReceipt
|
Receipt types.MessageReceipt
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,5 +2,19 @@
|
|||||||
|
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
|
|
||||||
sed "s/{{PARAMSJSON}}/$(base64 build/proof-params/parameters.json -w 0)/g" build/proof-params/paramfetch.sh.template > ./build/paramfetch.sh
|
function b64() {
|
||||||
|
f="$1"
|
||||||
|
case `uname` in
|
||||||
|
Darwin)
|
||||||
|
base64 -i "$f"
|
||||||
|
;;
|
||||||
|
Linux)
|
||||||
|
base64 "$f" -w 0
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
printf "unsupported system" 1>&2
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
sed "s/{{PARAMSJSON}}/$(b64 build/proof-params/parameters.json)/g" build/proof-params/paramfetch.sh.template > ./build/paramfetch.sh
|
||||||
chmod +x ./build/paramfetch.sh
|
chmod +x ./build/paramfetch.sh
|
||||||
|
@ -145,7 +145,7 @@ func cheatStorageMarketTotal(t *testing.T, vm *vm.VM, bs bstore.Blockstore) {
|
|||||||
|
|
||||||
func fakeBlock(t *testing.T, minerAddr address.Address, ts uint64) *types.BlockHeader {
|
func fakeBlock(t *testing.T, minerAddr address.Address, ts uint64) *types.BlockHeader {
|
||||||
c := fakeCid(t, 1)
|
c := fakeCid(t, 1)
|
||||||
return &types.BlockHeader{Height: 5, Miner: minerAddr, Timestamp: ts, StateRoot: c, Messages: c, MessageReceipts: c, BLSAggregate: types.Signature{Type: types.KTBLS}}
|
return &types.BlockHeader{Height: 5, Miner: minerAddr, Timestamp: ts, ParentStateRoot: c, Messages: c, ParentMessageReceipts: c, BLSAggregate: types.Signature{Type: types.KTBLS}}
|
||||||
}
|
}
|
||||||
|
|
||||||
func fakeCid(t *testing.T, s int) cid.Cid {
|
func fakeCid(t *testing.T, s int) cid.Cid {
|
||||||
|
@ -143,10 +143,7 @@ func (h *Handler) saveAsk(a *types.SignedStorageAsk) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) checkAskSignature(ask *types.SignedStorageAsk) error {
|
func (c *Client) checkAskSignature(ask *types.SignedStorageAsk) error {
|
||||||
tss, err := c.sm.TipSetState(c.sm.ChainStore().GetHeaviestTipSet().Cids())
|
tss := c.sm.ChainStore().GetHeaviestTipSet().ParentState()
|
||||||
if err != nil {
|
|
||||||
return xerrors.Errorf("failed to get tipsetstate to query for miner worker: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
w, err := stmgr.GetMinerWorker(context.TODO(), c.sm, tss, ask.Ask.Miner)
|
w, err := stmgr.GetMinerWorker(context.TODO(), c.sm, tss, ask.Ask.Miner)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -3,11 +3,12 @@ package events
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/filecoin-project/go-lotus/api"
|
|
||||||
"github.com/filecoin-project/go-lotus/chain/store"
|
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/filecoin-project/go-lotus/api"
|
||||||
|
"github.com/filecoin-project/go-lotus/chain/store"
|
||||||
|
|
||||||
"github.com/ipfs/go-cid"
|
"github.com/ipfs/go-cid"
|
||||||
"github.com/multiformats/go-multihash"
|
"github.com/multiformats/go-multihash"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
@ -48,9 +49,9 @@ func makeTs(t *testing.T, h uint64, msgcid cid.Cid) *types.TipSet {
|
|||||||
{
|
{
|
||||||
Height: h,
|
Height: h,
|
||||||
|
|
||||||
StateRoot: dummyCid,
|
ParentStateRoot: dummyCid,
|
||||||
Messages: msgcid,
|
Messages: msgcid,
|
||||||
MessageReceipts: dummyCid,
|
ParentMessageReceipts: dummyCid,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -608,5 +609,4 @@ func TestCalledOrder(t *testing.T) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
fcs.advance(9, 1, nil)
|
fcs.advance(9, 1, nil)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -3,8 +3,9 @@ package events
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/filecoin-project/go-lotus/chain/types"
|
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/filecoin-project/go-lotus/chain/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestTsCache(t *testing.T) {
|
func TestTsCache(t *testing.T) {
|
||||||
@ -17,10 +18,10 @@ func TestTsCache(t *testing.T) {
|
|||||||
|
|
||||||
add := func() {
|
add := func() {
|
||||||
ts, err := types.NewTipSet([]*types.BlockHeader{{
|
ts, err := types.NewTipSet([]*types.BlockHeader{{
|
||||||
Height: h,
|
Height: h,
|
||||||
StateRoot: dummyCid,
|
ParentStateRoot: dummyCid,
|
||||||
Messages: dummyCid,
|
Messages: dummyCid,
|
||||||
MessageReceipts: dummyCid,
|
ParentMessageReceipts: dummyCid,
|
||||||
}})
|
}})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
|
@ -201,10 +201,7 @@ func (cg *ChainGen) nextBlockProof(ctx context.Context, m address.Address, ticks
|
|||||||
lastTicket = ticks[len(ticks)-1]
|
lastTicket = ticks[len(ticks)-1]
|
||||||
}
|
}
|
||||||
|
|
||||||
st, err := cg.sm.TipSetState(pts.Cids())
|
st := cg.curTipset.TipSet().ParentState()
|
||||||
if err != nil {
|
|
||||||
return nil, nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
worker, err := stmgr.GetMinerWorker(ctx, cg.sm, st, m)
|
worker, err := stmgr.GetMinerWorker(ctx, cg.sm, st, m)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -258,7 +255,7 @@ func (cg *ChainGen) NextTipSet() (*MinedTipSet, error) {
|
|||||||
for i, m := range cg.miners {
|
for i, m := range cg.miners {
|
||||||
proof, t, err := cg.nextBlockProof(context.TODO(), m, ticketSets[i])
|
proof, t, err := cg.nextBlockProof(context.TODO(), m, ticketSets[i])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, xerrors.Errorf("next block proof: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
ticketSets[i] = append(ticketSets[i], t)
|
ticketSets[i] = append(ticketSets[i], t)
|
||||||
@ -269,7 +266,7 @@ func (cg *ChainGen) NextTipSet() (*MinedTipSet, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if err := cg.cs.AddBlock(fblk.Header); err != nil {
|
if err := cg.cs.AddBlock(fblk.Header); err != nil {
|
||||||
return nil, err
|
return nil, xerrors.Errorf("chainstore AddBlock: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
blks = append(blks, fblk)
|
blks = append(blks, fblk)
|
||||||
@ -376,12 +373,7 @@ func (mca mca) StateMinerPower(ctx context.Context, maddr address.Address, ts *t
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (mca mca) StateMinerWorker(ctx context.Context, maddr address.Address, ts *types.TipSet) (address.Address, error) {
|
func (mca mca) StateMinerWorker(ctx context.Context, maddr address.Address, ts *types.TipSet) (address.Address, error) {
|
||||||
st, err := mca.sm.TipSetState(ts.Cids())
|
return stmgr.GetMinerWorker(ctx, mca.sm, ts.ParentState(), maddr)
|
||||||
if err != nil {
|
|
||||||
return address.Undef, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return stmgr.GetMinerWorker(ctx, mca.sm, st, maddr)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (mca mca) WalletSign(ctx context.Context, a address.Address, v []byte) (*types.Signature, error) {
|
func (mca mca) WalletSign(ctx context.Context, a address.Address, v []byte) (*types.Signature, error) {
|
||||||
|
@ -20,7 +20,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func MinerCreateBlock(ctx context.Context, sm *stmgr.StateManager, w *wallet.Wallet, miner address.Address, parents *types.TipSet, tickets []*types.Ticket, proof types.ElectionProof, msgs []*types.SignedMessage, timestamp uint64) (*types.FullBlock, error) {
|
func MinerCreateBlock(ctx context.Context, sm *stmgr.StateManager, w *wallet.Wallet, miner address.Address, parents *types.TipSet, tickets []*types.Ticket, proof types.ElectionProof, msgs []*types.SignedMessage, timestamp uint64) (*types.FullBlock, error) {
|
||||||
st, err := sm.TipSetState(parents.Cids())
|
st, recpts, err := sm.TipSetState(parents)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "failed to load tipset state")
|
return nil, errors.Wrap(err, "failed to load tipset state")
|
||||||
}
|
}
|
||||||
@ -53,12 +53,14 @@ func MinerCreateBlock(ctx context.Context, sm *stmgr.StateManager, w *wallet.Wal
|
|||||||
}
|
}
|
||||||
|
|
||||||
next := &types.BlockHeader{
|
next := &types.BlockHeader{
|
||||||
Miner: miner,
|
Miner: miner,
|
||||||
Parents: parents.Cids(),
|
Parents: parents.Cids(),
|
||||||
Tickets: tickets,
|
Tickets: tickets,
|
||||||
Height: height,
|
Height: height,
|
||||||
Timestamp: timestamp,
|
Timestamp: timestamp,
|
||||||
ElectionProof: proof,
|
ElectionProof: proof,
|
||||||
|
ParentStateRoot: st,
|
||||||
|
ParentMessageReceipts: recpts,
|
||||||
}
|
}
|
||||||
|
|
||||||
var blsMessages []*types.Message
|
var blsMessages []*types.Message
|
||||||
@ -83,24 +85,6 @@ func MinerCreateBlock(ctx context.Context, sm *stmgr.StateManager, w *wallet.Wal
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var receipts []cbg.CBORMarshaler
|
|
||||||
for _, msg := range blsMessages {
|
|
||||||
rec, err := vmi.ApplyMessage(ctx, msg)
|
|
||||||
if err != nil {
|
|
||||||
return nil, errors.Wrap(err, "apply message failure")
|
|
||||||
}
|
|
||||||
|
|
||||||
receipts = append(receipts, &rec.MessageReceipt)
|
|
||||||
}
|
|
||||||
for _, msg := range secpkMessages {
|
|
||||||
rec, err := vmi.ApplyMessage(ctx, &msg.Message)
|
|
||||||
if err != nil {
|
|
||||||
return nil, errors.Wrap(err, "apply message failure")
|
|
||||||
}
|
|
||||||
|
|
||||||
receipts = append(receipts, &rec.MessageReceipt)
|
|
||||||
}
|
|
||||||
|
|
||||||
bs := amt.WrapBlockstore(sm.ChainStore().Blockstore())
|
bs := amt.WrapBlockstore(sm.ChainStore().Blockstore())
|
||||||
blsmsgroot, err := amt.FromArray(bs, toIfArr(blsMsgCids))
|
blsmsgroot, err := amt.FromArray(bs, toIfArr(blsMsgCids))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -120,24 +104,12 @@ func MinerCreateBlock(ctx context.Context, sm *stmgr.StateManager, w *wallet.Wal
|
|||||||
}
|
}
|
||||||
next.Messages = mmcid
|
next.Messages = mmcid
|
||||||
|
|
||||||
rectroot, err := amt.FromArray(bs, receipts)
|
|
||||||
if err != nil {
|
|
||||||
return nil, xerrors.Errorf("failed to build receipts amt: %w", err)
|
|
||||||
}
|
|
||||||
next.MessageReceipts = rectroot
|
|
||||||
|
|
||||||
stateRoot, err := vmi.Flush(context.TODO())
|
|
||||||
if err != nil {
|
|
||||||
return nil, errors.Wrap(err, "flushing state tree failed")
|
|
||||||
}
|
|
||||||
|
|
||||||
aggSig, err := aggregateSignatures(blsSigs)
|
aggSig, err := aggregateSignatures(blsSigs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
next.BLSAggregate = aggSig
|
next.BLSAggregate = aggSig
|
||||||
next.StateRoot = stateRoot
|
|
||||||
pweight := sm.ChainStore().Weight(parents)
|
pweight := sm.ChainStore().Weight(parents)
|
||||||
next.ParentWeight = types.NewInt(pweight)
|
next.ParentWeight = types.NewInt(pweight)
|
||||||
|
|
||||||
|
@ -335,18 +335,18 @@ func MakeGenesisBlock(bs bstore.Blockstore, balances map[address.Address]types.B
|
|||||||
}
|
}
|
||||||
|
|
||||||
b := &types.BlockHeader{
|
b := &types.BlockHeader{
|
||||||
Miner: actors.InitActorAddress,
|
Miner: actors.InitActorAddress,
|
||||||
Tickets: []*types.Ticket{genesisticket},
|
Tickets: []*types.Ticket{genesisticket},
|
||||||
ElectionProof: []byte("the Genesis block"),
|
ElectionProof: []byte("the Genesis block"),
|
||||||
Parents: []cid.Cid{},
|
Parents: []cid.Cid{},
|
||||||
Height: 0,
|
Height: 0,
|
||||||
ParentWeight: types.NewInt(0),
|
ParentWeight: types.NewInt(0),
|
||||||
StateRoot: stateroot,
|
ParentStateRoot: stateroot,
|
||||||
Messages: mmb.Cid(),
|
Messages: mmb.Cid(),
|
||||||
MessageReceipts: emptyroot,
|
ParentMessageReceipts: emptyroot,
|
||||||
BLSAggregate: types.Signature{Type: types.KTBLS, Data: []byte("signatureeee")},
|
BLSAggregate: types.Signature{Type: types.KTBLS, Data: []byte("signatureeee")},
|
||||||
BlockSig: types.Signature{Type: types.KTBLS, Data: []byte("block signatureeee")},
|
BlockSig: types.Signature{Type: types.KTBLS, Data: []byte("block signatureeee")},
|
||||||
Timestamp: ts,
|
Timestamp: ts,
|
||||||
}
|
}
|
||||||
|
|
||||||
sb, err := b.ToStorageBlock()
|
sb, err := b.ToStorageBlock()
|
||||||
|
@ -53,10 +53,7 @@ func (sm *StateManager) Call(ctx context.Context, msg *types.Message, ts *types.
|
|||||||
ts = sm.cs.GetHeaviestTipSet()
|
ts = sm.cs.GetHeaviestTipSet()
|
||||||
}
|
}
|
||||||
|
|
||||||
state, err := sm.TipSetState(ts.Cids())
|
state := ts.ParentState()
|
||||||
if err != nil {
|
|
||||||
return nil, xerrors.Errorf("getting tipset state: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
r := vm.NewChainRand(sm.cs, ts.Cids(), ts.Height(), nil)
|
r := vm.NewChainRand(sm.cs, ts.Cids(), ts.Height(), nil)
|
||||||
|
|
||||||
@ -69,7 +66,7 @@ func (sm *StateManager) Replay(ctx context.Context, ts *types.TipSet, mcid cid.C
|
|||||||
var outm *types.Message
|
var outm *types.Message
|
||||||
var outr *vm.ApplyRet
|
var outr *vm.ApplyRet
|
||||||
|
|
||||||
_, err := sm.computeTipSetState(ctx, ts.Blocks(), func(c cid.Cid, m *types.Message, ret *vm.ApplyRet) error {
|
_, _, err := sm.computeTipSetState(ctx, ts.Blocks(), func(c cid.Cid, m *types.Message, ret *vm.ApplyRet) error {
|
||||||
if c == mcid {
|
if c == mcid {
|
||||||
outm = m
|
outm = m
|
||||||
outr = ret
|
outr = ret
|
||||||
|
@ -4,11 +4,14 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
|
amt "github.com/filecoin-project/go-amt-ipld"
|
||||||
|
"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/state"
|
"github.com/filecoin-project/go-lotus/chain/state"
|
||||||
"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/vm"
|
"github.com/filecoin-project/go-lotus/chain/vm"
|
||||||
|
cbg "github.com/whyrusleeping/cbor-gen"
|
||||||
"golang.org/x/xerrors"
|
"golang.org/x/xerrors"
|
||||||
|
|
||||||
"github.com/ipfs/go-cid"
|
"github.com/ipfs/go-cid"
|
||||||
@ -21,14 +24,14 @@ var log = logging.Logger("statemgr")
|
|||||||
type StateManager struct {
|
type StateManager struct {
|
||||||
cs *store.ChainStore
|
cs *store.ChainStore
|
||||||
|
|
||||||
stCache map[string]cid.Cid
|
stCache map[string][]cid.Cid
|
||||||
stlk sync.Mutex
|
stlk sync.Mutex
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewStateManager(cs *store.ChainStore) *StateManager {
|
func NewStateManager(cs *store.ChainStore) *StateManager {
|
||||||
return &StateManager{
|
return &StateManager{
|
||||||
cs: cs,
|
cs: cs,
|
||||||
stCache: make(map[string]cid.Cid),
|
stCache: make(map[string][]cid.Cid),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -40,42 +43,38 @@ func cidsToKey(cids []cid.Cid) string {
|
|||||||
return out
|
return out
|
||||||
}
|
}
|
||||||
|
|
||||||
func (sm *StateManager) TipSetState(cids []cid.Cid) (cid.Cid, error) {
|
func (sm *StateManager) TipSetState(ts *types.TipSet) (cid.Cid, cid.Cid, error) {
|
||||||
ctx := context.TODO()
|
ctx := context.TODO()
|
||||||
|
|
||||||
ck := cidsToKey(cids)
|
ck := cidsToKey(ts.Cids())
|
||||||
sm.stlk.Lock()
|
sm.stlk.Lock()
|
||||||
cached, ok := sm.stCache[ck]
|
cached, ok := sm.stCache[ck]
|
||||||
sm.stlk.Unlock()
|
sm.stlk.Unlock()
|
||||||
if ok {
|
if ok {
|
||||||
return cached, nil
|
return cached[0], cached[1], nil
|
||||||
}
|
}
|
||||||
|
|
||||||
ts, err := sm.cs.LoadTipSet(cids)
|
if ts.Height() == 0 {
|
||||||
if err != nil {
|
// NB: This is here because the process that executes blocks requires that the
|
||||||
return cid.Undef, err
|
// block miner reference a valid miner in the state tree. Unless we create some
|
||||||
|
// magical genesis miner, this won't work properly, so we short circuit here
|
||||||
|
// This avoids the question of 'who gets paid the genesis block reward'
|
||||||
|
return ts.Blocks()[0].ParentStateRoot, ts.Blocks()[0].ParentMessageReceipts, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
out, err := sm.computeTipSetState(ctx, ts.Blocks(), nil)
|
st, rec, err := sm.computeTipSetState(ctx, ts.Blocks(), nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return cid.Undef, err
|
return cid.Undef, cid.Undef, err
|
||||||
}
|
}
|
||||||
|
|
||||||
sm.stlk.Lock()
|
sm.stlk.Lock()
|
||||||
sm.stCache[ck] = out
|
sm.stCache[ck] = []cid.Cid{st, rec}
|
||||||
sm.stlk.Unlock()
|
sm.stlk.Unlock()
|
||||||
return out, nil
|
return st, rec, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (sm *StateManager) computeTipSetState(ctx context.Context, blks []*types.BlockHeader, cb func(cid.Cid, *types.Message, *vm.ApplyRet) error) (cid.Cid, error) {
|
func (sm *StateManager) computeTipSetState(ctx context.Context, blks []*types.BlockHeader, cb func(cid.Cid, *types.Message, *vm.ApplyRet) error) (cid.Cid, cid.Cid, error) {
|
||||||
if len(blks) == 1 && cb == nil {
|
pstate := blks[0].ParentStateRoot
|
||||||
return blks[0].StateRoot, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
pstate, err := sm.TipSetState(blks[0].Parents)
|
|
||||||
if err != nil {
|
|
||||||
return cid.Undef, xerrors.Errorf("recursive TipSetState failed: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
cids := make([]cid.Cid, len(blks))
|
cids := make([]cid.Cid, len(blks))
|
||||||
for i, v := range blks {
|
for i, v := range blks {
|
||||||
@ -86,56 +85,110 @@ func (sm *StateManager) computeTipSetState(ctx context.Context, blks []*types.Bl
|
|||||||
|
|
||||||
vmi, err := vm.NewVM(pstate, blks[0].Height, r, address.Undef, sm.cs)
|
vmi, err := vm.NewVM(pstate, blks[0].Height, r, address.Undef, sm.cs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return cid.Undef, xerrors.Errorf("instantiating VM failed: %w", err)
|
return cid.Undef, cid.Undef, xerrors.Errorf("instantiating VM failed: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
applied := make(map[cid.Cid]bool)
|
netact, err := vmi.StateTree().GetActor(actors.NetworkAddress)
|
||||||
|
if err != nil {
|
||||||
|
return cid.Undef, cid.Undef, xerrors.Errorf("failed to get network actor: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
reward := vm.MiningReward(netact.Balance)
|
||||||
|
for _, b := range blks {
|
||||||
|
owner, err := GetMinerOwner(ctx, sm, pstate, b.Miner)
|
||||||
|
if err != nil {
|
||||||
|
return cid.Undef, cid.Undef, xerrors.Errorf("failed to get owner for miner %s: %w", b.Miner, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
act, err := vmi.StateTree().GetActor(owner)
|
||||||
|
if err != nil {
|
||||||
|
return cid.Undef, cid.Undef, xerrors.Errorf("failed to get miner owner actor")
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := vm.DeductFunds(netact, reward); err != nil {
|
||||||
|
return cid.Undef, cid.Undef, xerrors.Errorf("failed to deduct funds from network actor: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
vm.DepositFunds(act, reward)
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: can't use method from chainstore because it doesnt let us know who the block miners were
|
||||||
|
applied := make(map[address.Address]uint64)
|
||||||
|
balances := make(map[address.Address]types.BigInt)
|
||||||
|
|
||||||
|
preloadAddr := func(a address.Address) error {
|
||||||
|
if _, ok := applied[a]; !ok {
|
||||||
|
act, err := vmi.StateTree().GetActor(a)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
applied[a] = act.Nonce
|
||||||
|
balances[a] = act.Balance
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var receipts []cbg.CBORMarshaler
|
||||||
for _, b := range blks {
|
for _, b := range blks {
|
||||||
vmi.SetBlockMiner(b.Miner)
|
vmi.SetBlockMiner(b.Miner)
|
||||||
|
|
||||||
bms, sms, err := sm.cs.MessagesForBlock(b)
|
bms, sms, err := sm.cs.MessagesForBlock(b)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return cid.Undef, xerrors.Errorf("failed to get messages for block: %w", err)
|
return cid.Undef, cid.Undef, xerrors.Errorf("failed to get messages for block: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cmsgs := make([]store.ChainMsg, 0, len(bms)+len(sms))
|
||||||
for _, m := range bms {
|
for _, m := range bms {
|
||||||
if applied[m.Cid()] {
|
cmsgs = append(cmsgs, m)
|
||||||
|
}
|
||||||
|
for _, sm := range sms {
|
||||||
|
cmsgs = append(cmsgs, sm)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, cm := range cmsgs {
|
||||||
|
m := cm.VMMessage()
|
||||||
|
if err := preloadAddr(m.From); err != nil {
|
||||||
|
return cid.Undef, cid.Undef, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if applied[m.From] != m.Nonce {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
applied[m.Cid()] = true
|
applied[m.From]++
|
||||||
|
|
||||||
|
if balances[m.From].LessThan(m.RequiredFunds()) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
balances[m.From] = types.BigSub(balances[m.From], m.RequiredFunds())
|
||||||
|
|
||||||
r, err := vmi.ApplyMessage(ctx, m)
|
r, err := vmi.ApplyMessage(ctx, m)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return cid.Undef, err
|
return cid.Undef, cid.Undef, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
receipts = append(receipts, &r.MessageReceipt)
|
||||||
|
|
||||||
if cb != nil {
|
if cb != nil {
|
||||||
if err := cb(m.Cid(), m, r); err != nil {
|
if err := cb(cm.Cid(), m, r); err != nil {
|
||||||
return cid.Undef, err
|
return cid.Undef, cid.Undef, err
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, sm := range sms {
|
|
||||||
if applied[sm.Cid()] {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
applied[sm.Cid()] = true
|
|
||||||
|
|
||||||
r, err := vmi.ApplyMessage(ctx, &sm.Message)
|
|
||||||
if err != nil {
|
|
||||||
return cid.Undef, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if cb != nil {
|
|
||||||
if err := cb(sm.Cid(), &sm.Message, r); err != nil {
|
|
||||||
return cid.Undef, err
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return vmi.Flush(ctx)
|
bs := amt.WrapBlockstore(sm.cs.Blockstore())
|
||||||
|
rectroot, err := amt.FromArray(bs, receipts)
|
||||||
|
if err != nil {
|
||||||
|
return cid.Undef, cid.Undef, xerrors.Errorf("failed to build receipts amt: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
st, err := vmi.Flush(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return cid.Undef, cid.Undef, xerrors.Errorf("vm flush failed: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return st, rectroot, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (sm *StateManager) GetActor(addr address.Address, ts *types.TipSet) (*types.Actor, error) {
|
func (sm *StateManager) GetActor(addr address.Address, ts *types.TipSet) (*types.Actor, error) {
|
||||||
@ -143,10 +196,7 @@ func (sm *StateManager) GetActor(addr address.Address, ts *types.TipSet) (*types
|
|||||||
ts = sm.cs.GetHeaviestTipSet()
|
ts = sm.cs.GetHeaviestTipSet()
|
||||||
}
|
}
|
||||||
|
|
||||||
stcid, err := sm.TipSetState(ts.Cids())
|
stcid := ts.ParentState()
|
||||||
if err != nil {
|
|
||||||
return nil, xerrors.Errorf("tipset state: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
cst := hamt.CSTFromBstore(sm.cs.Blockstore())
|
cst := hamt.CSTFromBstore(sm.cs.Blockstore())
|
||||||
state, err := state.LoadStateTree(cst, stcid)
|
state, err := state.LoadStateTree(cst, stcid)
|
||||||
|
@ -8,6 +8,8 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"github.com/filecoin-project/go-lotus/build"
|
"github.com/filecoin-project/go-lotus/build"
|
||||||
|
"github.com/filecoin-project/go-lotus/chain/address"
|
||||||
|
"github.com/filecoin-project/go-lotus/chain/state"
|
||||||
|
|
||||||
amt "github.com/filecoin-project/go-amt-ipld"
|
amt "github.com/filecoin-project/go-amt-ipld"
|
||||||
"github.com/filecoin-project/go-lotus/chain/types"
|
"github.com/filecoin-project/go-lotus/chain/types"
|
||||||
@ -519,6 +521,72 @@ func (cs *ChainStore) readAMTCids(root cid.Cid) ([]cid.Cid, error) {
|
|||||||
return cids, nil
|
return cids, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type ChainMsg interface {
|
||||||
|
Cid() cid.Cid
|
||||||
|
VMMessage() *types.Message
|
||||||
|
}
|
||||||
|
|
||||||
|
func (cs *ChainStore) MessagesForTipset(ts *types.TipSet) ([]ChainMsg, error) {
|
||||||
|
applied := make(map[address.Address]uint64)
|
||||||
|
balances := make(map[address.Address]types.BigInt)
|
||||||
|
|
||||||
|
cst := hamt.CSTFromBstore(cs.bs)
|
||||||
|
st, err := state.LoadStateTree(cst, ts.Blocks()[0].ParentStateRoot)
|
||||||
|
if err != nil {
|
||||||
|
return nil, xerrors.Errorf("failed to load state tree")
|
||||||
|
}
|
||||||
|
|
||||||
|
preloadAddr := func(a address.Address) error {
|
||||||
|
if _, ok := applied[a]; !ok {
|
||||||
|
act, err := st.GetActor(a)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
applied[a] = act.Nonce
|
||||||
|
balances[a] = act.Balance
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var out []ChainMsg
|
||||||
|
for _, b := range ts.Blocks() {
|
||||||
|
bms, sms, err := cs.MessagesForBlock(b)
|
||||||
|
if err != nil {
|
||||||
|
return nil, xerrors.Errorf("failed to get messages for block: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
cmsgs := make([]ChainMsg, 0, len(bms)+len(sms))
|
||||||
|
for _, m := range bms {
|
||||||
|
cmsgs = append(cmsgs, m)
|
||||||
|
}
|
||||||
|
for _, sm := range sms {
|
||||||
|
cmsgs = append(cmsgs, sm)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, cm := range cmsgs {
|
||||||
|
m := cm.VMMessage()
|
||||||
|
if err := preloadAddr(m.From); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if applied[m.From] != m.Nonce {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
applied[m.From]++
|
||||||
|
|
||||||
|
if balances[m.From].LessThan(m.RequiredFunds()) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
balances[m.From] = types.BigSub(balances[m.From], m.RequiredFunds())
|
||||||
|
|
||||||
|
out = append(out, cm)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return out, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (cs *ChainStore) MessagesForBlock(b *types.BlockHeader) ([]*types.Message, []*types.SignedMessage, error) {
|
func (cs *ChainStore) MessagesForBlock(b *types.BlockHeader) ([]*types.Message, []*types.SignedMessage, error) {
|
||||||
cst := hamt.CSTFromBstore(cs.bs)
|
cst := hamt.CSTFromBstore(cs.bs)
|
||||||
var msgmeta types.MsgMeta
|
var msgmeta types.MsgMeta
|
||||||
@ -551,7 +619,7 @@ func (cs *ChainStore) MessagesForBlock(b *types.BlockHeader) ([]*types.Message,
|
|||||||
|
|
||||||
func (cs *ChainStore) GetReceipt(b *types.BlockHeader, i int) (*types.MessageReceipt, error) {
|
func (cs *ChainStore) GetReceipt(b *types.BlockHeader, i int) (*types.MessageReceipt, error) {
|
||||||
bs := amt.WrapBlockstore(cs.bs)
|
bs := amt.WrapBlockstore(cs.bs)
|
||||||
a, err := amt.LoadAMT(bs, b.MessageReceipts)
|
a, err := amt.LoadAMT(bs, b.ParentMessageReceipts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "amt load")
|
return nil, errors.Wrap(err, "amt load")
|
||||||
}
|
}
|
||||||
@ -592,57 +660,69 @@ func (cs *ChainStore) LoadSignedMessagesFromCids(cids []cid.Cid) ([]*types.Signe
|
|||||||
return msgs, nil
|
return msgs, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cs *ChainStore) WaitForMessage(ctx context.Context, mcid cid.Cid) (cid.Cid, *types.MessageReceipt, error) {
|
func (cs *ChainStore) WaitForMessage(ctx context.Context, mcid cid.Cid) (*types.MessageReceipt, error) {
|
||||||
tsub := cs.SubHeadChanges(ctx)
|
tsub := cs.SubHeadChanges(ctx)
|
||||||
|
|
||||||
head := cs.GetHeaviestTipSet()
|
head := cs.GetHeaviestTipSet()
|
||||||
|
|
||||||
bc, r, err := cs.tipsetContainsMsg(head, mcid)
|
r, err := cs.tipsetExecutedMessage(head, mcid)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return cid.Undef, nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if r != nil {
|
if r != nil {
|
||||||
return bc, r, nil
|
return r, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
case notif, ok := <-tsub:
|
case notif, ok := <-tsub:
|
||||||
if !ok {
|
if !ok {
|
||||||
return cid.Undef, nil, ctx.Err()
|
return nil, ctx.Err()
|
||||||
}
|
}
|
||||||
for _, val := range notif {
|
for _, val := range notif {
|
||||||
switch val.Type {
|
switch val.Type {
|
||||||
case HCRevert:
|
case HCRevert:
|
||||||
continue
|
continue
|
||||||
case HCApply:
|
case HCApply:
|
||||||
bc, r, err := cs.tipsetContainsMsg(val.Val, mcid)
|
r, err := cs.tipsetExecutedMessage(val.Val, mcid)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return cid.Undef, nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if r != nil {
|
if r != nil {
|
||||||
return bc, r, nil
|
return r, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case <-ctx.Done():
|
case <-ctx.Done():
|
||||||
return cid.Undef, nil, ctx.Err()
|
return nil, ctx.Err()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cs *ChainStore) tipsetContainsMsg(ts *types.TipSet, msg cid.Cid) (cid.Cid, *types.MessageReceipt, error) {
|
func (cs *ChainStore) tipsetExecutedMessage(ts *types.TipSet, msg cid.Cid) (*types.MessageReceipt, error) {
|
||||||
for _, b := range ts.Blocks() {
|
// The genesis block did not execute any messages
|
||||||
r, err := cs.blockContainsMsg(b, msg)
|
if ts.Height() == 0 {
|
||||||
if err != nil {
|
return nil, nil
|
||||||
return cid.Undef, nil, err
|
}
|
||||||
}
|
|
||||||
if r != nil {
|
pts, err := cs.LoadTipSet(ts.Parents())
|
||||||
return b.Cid(), r, nil
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
cm, err := cs.MessagesForTipset(pts)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, m := range cm {
|
||||||
|
if m.Cid() == msg {
|
||||||
|
return cs.GetReceipt(ts.Blocks()[0], i)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return cid.Undef, nil, nil
|
|
||||||
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cs *ChainStore) blockContainsMsg(blk *types.BlockHeader, msg cid.Cid) (*types.MessageReceipt, error) {
|
func (cs *ChainStore) blockContainsMsg(blk *types.BlockHeader, msg cid.Cid) (*types.MessageReceipt, error) {
|
||||||
|
101
chain/sync.go
101
chain/sync.go
@ -10,15 +10,16 @@ import (
|
|||||||
"github.com/filecoin-project/go-lotus/build"
|
"github.com/filecoin-project/go-lotus/build"
|
||||||
"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/state"
|
||||||
"github.com/filecoin-project/go-lotus/chain/stmgr"
|
"github.com/filecoin-project/go-lotus/chain/stmgr"
|
||||||
"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/vm"
|
|
||||||
"github.com/filecoin-project/go-lotus/lib/vdf"
|
"github.com/filecoin-project/go-lotus/lib/vdf"
|
||||||
|
|
||||||
amt "github.com/filecoin-project/go-amt-ipld"
|
amt "github.com/filecoin-project/go-amt-ipld"
|
||||||
"github.com/ipfs/go-cid"
|
"github.com/ipfs/go-cid"
|
||||||
dstore "github.com/ipfs/go-datastore"
|
dstore "github.com/ipfs/go-datastore"
|
||||||
|
hamt "github.com/ipfs/go-hamt-ipld"
|
||||||
bstore "github.com/ipfs/go-ipfs-blockstore"
|
bstore "github.com/ipfs/go-ipfs-blockstore"
|
||||||
logging "github.com/ipfs/go-log"
|
logging "github.com/ipfs/go-log"
|
||||||
"github.com/libp2p/go-libp2p-core/peer"
|
"github.com/libp2p/go-libp2p-core/peer"
|
||||||
@ -380,16 +381,25 @@ func (syncer *Syncer) validateTickets(ctx context.Context, mworker address.Addre
|
|||||||
// Should match up with 'Semantical Validation' in validation.md in the spec
|
// Should match up with 'Semantical Validation' in validation.md in the spec
|
||||||
func (syncer *Syncer) ValidateBlock(ctx context.Context, b *types.FullBlock) error {
|
func (syncer *Syncer) ValidateBlock(ctx context.Context, b *types.FullBlock) error {
|
||||||
h := b.Header
|
h := b.Header
|
||||||
stateroot, err := syncer.sm.TipSetState(h.Parents)
|
|
||||||
if err != nil {
|
|
||||||
return xerrors.Errorf("get tipsetstate(%d, %s) failed: %w", h.Height, h.Parents, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
baseTs, err := syncer.store.LoadTipSet(h.Parents)
|
baseTs, err := syncer.store.LoadTipSet(h.Parents)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return xerrors.Errorf("load tipset failed: %w", err)
|
return xerrors.Errorf("load tipset failed: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
stateroot, precp, err := syncer.sm.TipSetState(baseTs)
|
||||||
|
if err != nil {
|
||||||
|
return xerrors.Errorf("get tipsetstate(%d, %s) failed: %w", h.Height, h.Parents, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if stateroot != h.ParentStateRoot {
|
||||||
|
return xerrors.Errorf("parent state root did not match computed state (%s != %s)", stateroot, h.ParentStateRoot)
|
||||||
|
}
|
||||||
|
|
||||||
|
if precp != h.ParentMessageReceipts {
|
||||||
|
return xerrors.Errorf("parent receipts root did not match computed value (%s != %s)", precp, h.ParentMessageReceipts)
|
||||||
|
}
|
||||||
|
|
||||||
if h.Timestamp > uint64(time.Now().Unix()+build.AllowableClockDrift) {
|
if h.Timestamp > uint64(time.Now().Unix()+build.AllowableClockDrift) {
|
||||||
return xerrors.Errorf("block was from the future")
|
return xerrors.Errorf("block was from the future")
|
||||||
}
|
}
|
||||||
@ -434,61 +444,48 @@ func (syncer *Syncer) ValidateBlock(ctx context.Context, b *types.FullBlock) err
|
|||||||
return xerrors.Errorf("miner created a block but was not a winner")
|
return xerrors.Errorf("miner created a block but was not a winner")
|
||||||
}
|
}
|
||||||
|
|
||||||
r := vm.NewChainRand(syncer.store, baseTs.Cids(), baseTs.Height(), h.Tickets)
|
nonces := make(map[address.Address]uint64)
|
||||||
vmi, err := vm.NewVM(stateroot, h.Height, r, h.Miner, syncer.store)
|
balances := make(map[address.Address]types.BigInt)
|
||||||
|
|
||||||
|
cst := hamt.CSTFromBstore(syncer.store.Blockstore())
|
||||||
|
st, err := state.LoadStateTree(cst, stateroot)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return xerrors.Errorf("failed to instantiate VM: %w", err)
|
return xerrors.Errorf("failed to load base state tree: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
owner, err := stmgr.GetMinerOwner(ctx, syncer.sm, stateroot, b.Header.Miner)
|
checkMsg := func(m *types.Message) error {
|
||||||
if err != nil {
|
if _, ok := nonces[m.From]; !ok {
|
||||||
return xerrors.Errorf("getting miner owner for block miner failed: %w", err)
|
act, err := st.GetActor(m.From)
|
||||||
}
|
if err != nil {
|
||||||
networkBalance, err := vmi.ActorBalance(actors.NetworkAddress)
|
return xerrors.Errorf("failed to get actor: %w", err)
|
||||||
if err != nil {
|
}
|
||||||
return xerrors.Errorf("getting network balance")
|
nonces[m.From] = act.Nonce
|
||||||
}
|
balances[m.From] = act.Balance
|
||||||
|
|
||||||
if err := vmi.TransferFunds(actors.NetworkAddress, owner,
|
|
||||||
vm.MiningReward(networkBalance)); err != nil {
|
|
||||||
return xerrors.Errorf("fund transfer failed: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
var receipts []cbg.CBORMarshaler
|
|
||||||
for i, m := range b.BlsMessages {
|
|
||||||
receipt, err := vmi.ApplyMessage(ctx, m)
|
|
||||||
if err != nil {
|
|
||||||
return xerrors.Errorf("failed executing bls message %d in block %s: %w", i, b.Header.Cid(), err)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
receipts = append(receipts, &receipt.MessageReceipt)
|
if nonces[m.From] != m.Nonce {
|
||||||
|
return xerrors.Errorf("wrong nonce")
|
||||||
|
}
|
||||||
|
nonces[m.From]++
|
||||||
|
|
||||||
|
if balances[m.From].LessThan(m.RequiredFunds()) {
|
||||||
|
return xerrors.Errorf("not enough funds for message execution")
|
||||||
|
}
|
||||||
|
|
||||||
|
balances[m.From] = types.BigSub(balances[m.From], m.RequiredFunds())
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, m := range b.BlsMessages {
|
||||||
|
if err := checkMsg(m); err != nil {
|
||||||
|
xerrors.Errorf("block had invalid bls message at index %d: %w", i, err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for i, m := range b.SecpkMessages {
|
for i, m := range b.SecpkMessages {
|
||||||
receipt, err := vmi.ApplyMessage(ctx, &m.Message)
|
if err := checkMsg(&m.Message); err != nil {
|
||||||
if err != nil {
|
xerrors.Errorf("block had invalid secpk message at index %d: %w", i, err)
|
||||||
return xerrors.Errorf("failed executing secpk message %d in block %s: %w", i, b.Header.Cid(), err)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
receipts = append(receipts, &receipt.MessageReceipt)
|
|
||||||
}
|
|
||||||
|
|
||||||
bs := amt.WrapBlockstore(syncer.store.Blockstore())
|
|
||||||
recptRoot, err := amt.FromArray(bs, receipts)
|
|
||||||
if err != nil {
|
|
||||||
return xerrors.Errorf("building receipts amt failed: %w", err)
|
|
||||||
}
|
|
||||||
if recptRoot != b.Header.MessageReceipts {
|
|
||||||
return fmt.Errorf("receipts mismatched")
|
|
||||||
}
|
|
||||||
|
|
||||||
final, err := vmi.Flush(context.TODO())
|
|
||||||
if err != nil {
|
|
||||||
return xerrors.Errorf("failed to flush VM state: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if b.Header.StateRoot != final {
|
|
||||||
return fmt.Errorf("final state root does not match block")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
@ -549,7 +546,7 @@ loop:
|
|||||||
blockSet = append(blockSet, b)
|
blockSet = append(blockSet, b)
|
||||||
}
|
}
|
||||||
|
|
||||||
syncer.syncState.SetHeight(blks[len(blockSet)-1].Height())
|
syncer.syncState.SetHeight(blks[len(blks)-1].Height())
|
||||||
at = blks[len(blks)-1].Parents()
|
at = blks[len(blks)-1].Parents()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -34,14 +34,14 @@ type BlockHeader struct {
|
|||||||
|
|
||||||
Height uint64
|
Height uint64
|
||||||
|
|
||||||
StateRoot cid.Cid
|
ParentStateRoot cid.Cid
|
||||||
|
|
||||||
|
ParentMessageReceipts cid.Cid
|
||||||
|
|
||||||
Messages cid.Cid
|
Messages cid.Cid
|
||||||
|
|
||||||
BLSAggregate Signature
|
BLSAggregate Signature
|
||||||
|
|
||||||
MessageReceipts cid.Cid
|
|
||||||
|
|
||||||
Timestamp uint64
|
Timestamp uint64
|
||||||
|
|
||||||
BlockSig Signature
|
BlockSig Signature
|
||||||
|
@ -32,14 +32,14 @@ func testBlockHeader(t testing.TB) *BlockHeader {
|
|||||||
VDFProof: []byte("vrf proof"),
|
VDFProof: []byte("vrf proof"),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Parents: []cid.Cid{c, c},
|
Parents: []cid.Cid{c, c},
|
||||||
MessageReceipts: c,
|
ParentMessageReceipts: c,
|
||||||
BLSAggregate: Signature{Type: KTBLS, Data: []byte("boo! im a signature")},
|
BLSAggregate: Signature{Type: KTBLS, Data: []byte("boo! im a signature")},
|
||||||
ParentWeight: NewInt(123125126212),
|
ParentWeight: NewInt(123125126212),
|
||||||
Messages: c,
|
Messages: c,
|
||||||
Height: 85919298723,
|
Height: 85919298723,
|
||||||
StateRoot: c,
|
ParentStateRoot: c,
|
||||||
BlockSig: Signature{Type: KTBLS, Data: []byte("boo! im a signature")},
|
BlockSig: Signature{Type: KTBLS, Data: []byte("boo! im a signature")},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,7 +5,7 @@ import (
|
|||||||
"io"
|
"io"
|
||||||
"math"
|
"math"
|
||||||
|
|
||||||
"github.com/ipfs/go-cid"
|
cid "github.com/ipfs/go-cid"
|
||||||
cbg "github.com/whyrusleeping/cbor-gen"
|
cbg "github.com/whyrusleeping/cbor-gen"
|
||||||
xerrors "golang.org/x/xerrors"
|
xerrors "golang.org/x/xerrors"
|
||||||
)
|
)
|
||||||
@ -66,10 +66,16 @@ func (t *BlockHeader) MarshalCBOR(w io.Writer) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// t.t.StateRoot (cid.Cid)
|
// t.t.ParentStateRoot (cid.Cid)
|
||||||
|
|
||||||
if err := cbg.WriteCid(w, t.StateRoot); err != nil {
|
if err := cbg.WriteCid(w, t.ParentStateRoot); err != nil {
|
||||||
return xerrors.Errorf("failed to write cid field t.StateRoot: %w", err)
|
return xerrors.Errorf("failed to write cid field t.ParentStateRoot: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// t.t.ParentMessageReceipts (cid.Cid)
|
||||||
|
|
||||||
|
if err := cbg.WriteCid(w, t.ParentMessageReceipts); err != nil {
|
||||||
|
return xerrors.Errorf("failed to write cid field t.ParentMessageReceipts: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// t.t.Messages (cid.Cid)
|
// t.t.Messages (cid.Cid)
|
||||||
@ -83,12 +89,6 @@ func (t *BlockHeader) MarshalCBOR(w io.Writer) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// t.t.MessageReceipts (cid.Cid)
|
|
||||||
|
|
||||||
if err := cbg.WriteCid(w, t.MessageReceipts); err != nil {
|
|
||||||
return xerrors.Errorf("failed to write cid field t.MessageReceipts: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// t.t.Timestamp (uint64)
|
// t.t.Timestamp (uint64)
|
||||||
if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajUnsignedInt, t.Timestamp)); err != nil {
|
if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajUnsignedInt, t.Timestamp)); err != nil {
|
||||||
return err
|
return err
|
||||||
@ -212,16 +212,28 @@ func (t *BlockHeader) UnmarshalCBOR(r io.Reader) error {
|
|||||||
return fmt.Errorf("wrong type for uint64 field")
|
return fmt.Errorf("wrong type for uint64 field")
|
||||||
}
|
}
|
||||||
t.Height = extra
|
t.Height = extra
|
||||||
// t.t.StateRoot (cid.Cid)
|
// t.t.ParentStateRoot (cid.Cid)
|
||||||
|
|
||||||
{
|
{
|
||||||
|
|
||||||
c, err := cbg.ReadCid(br)
|
c, err := cbg.ReadCid(br)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return xerrors.Errorf("failed to read cid field t.StateRoot: %w", err)
|
return xerrors.Errorf("failed to read cid field t.ParentStateRoot: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
t.StateRoot = c
|
t.ParentStateRoot = c
|
||||||
|
|
||||||
|
}
|
||||||
|
// t.t.ParentMessageReceipts (cid.Cid)
|
||||||
|
|
||||||
|
{
|
||||||
|
|
||||||
|
c, err := cbg.ReadCid(br)
|
||||||
|
if err != nil {
|
||||||
|
return xerrors.Errorf("failed to read cid field t.ParentMessageReceipts: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
t.ParentMessageReceipts = c
|
||||||
|
|
||||||
}
|
}
|
||||||
// t.t.Messages (cid.Cid)
|
// t.t.Messages (cid.Cid)
|
||||||
@ -244,18 +256,6 @@ func (t *BlockHeader) UnmarshalCBOR(r io.Reader) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
|
||||||
// t.t.MessageReceipts (cid.Cid)
|
|
||||||
|
|
||||||
{
|
|
||||||
|
|
||||||
c, err := cbg.ReadCid(br)
|
|
||||||
if err != nil {
|
|
||||||
return xerrors.Errorf("failed to read cid field t.MessageReceipts: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
t.MessageReceipts = c
|
|
||||||
|
|
||||||
}
|
}
|
||||||
// t.t.Timestamp (uint64)
|
// t.t.Timestamp (uint64)
|
||||||
|
|
||||||
|
@ -73,3 +73,7 @@ func (m *Message) RequiredFunds() BigInt {
|
|||||||
BigMul(m.GasPrice, m.GasLimit),
|
BigMul(m.GasPrice, m.GasLimit),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (m *Message) VMMessage() *Message {
|
||||||
|
return m
|
||||||
|
}
|
||||||
|
@ -57,3 +57,7 @@ func (sm *SignedMessage) Serialize() ([]byte, error) {
|
|||||||
}
|
}
|
||||||
return buf.Bytes(), nil
|
return buf.Bytes(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (sm *SignedMessage) VMMessage() *Message {
|
||||||
|
return &sm.Message
|
||||||
|
}
|
||||||
|
@ -150,6 +150,10 @@ func (ts *TipSet) MinTicketBlock() *BlockHeader {
|
|||||||
return min
|
return min
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (ts *TipSet) ParentState() cid.Cid {
|
||||||
|
return ts.blks[0].ParentStateRoot
|
||||||
|
}
|
||||||
|
|
||||||
func (ts *TipSet) Contains(oc cid.Cid) bool {
|
func (ts *TipSet) Contains(oc cid.Cid) bool {
|
||||||
for _, c := range ts.cids {
|
for _, c := range ts.cids {
|
||||||
if c == oc {
|
if c == oc {
|
||||||
|
@ -112,7 +112,6 @@ var createMinerCmd = &cli.Command{
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Printf("miner created in block %s\n", mwait.InBlock)
|
|
||||||
fmt.Printf("new miner address: %s\n", maddr)
|
fmt.Printf("new miner address: %s\n", maddr)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
@ -51,13 +51,12 @@ func (a *ChainAPI) ChainGetRandomness(ctx context.Context, pts *types.TipSet, ti
|
|||||||
func (a *ChainAPI) ChainWaitMsg(ctx context.Context, msg cid.Cid) (*api.MsgWait, error) {
|
func (a *ChainAPI) ChainWaitMsg(ctx context.Context, msg cid.Cid) (*api.MsgWait, error) {
|
||||||
// TODO: consider using event system for this, expose confidence
|
// TODO: consider using event system for this, expose confidence
|
||||||
|
|
||||||
blkcid, recpt, err := a.Chain.WaitForMessage(ctx, msg)
|
recpt, err := a.Chain.WaitForMessage(ctx, msg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return &api.MsgWait{
|
return &api.MsgWait{
|
||||||
InBlock: blkcid,
|
|
||||||
Receipt: *recpt,
|
Receipt: *recpt,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@ package full
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
|
||||||
"go.uber.org/fx"
|
"go.uber.org/fx"
|
||||||
"golang.org/x/xerrors"
|
"golang.org/x/xerrors"
|
||||||
|
|
||||||
|
@ -134,7 +134,7 @@ func (a *StateAPI) stateForTs(ts *types.TipSet) (*state.StateTree, error) {
|
|||||||
ts = a.Chain.GetHeaviestTipSet()
|
ts = a.Chain.GetHeaviestTipSet()
|
||||||
}
|
}
|
||||||
|
|
||||||
st, err := a.StateManager.TipSetState(ts.Cids())
|
st, _, err := a.StateManager.TipSetState(ts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user