wip
This commit is contained in:
parent
48b7945714
commit
41ab87e904
@ -6,21 +6,28 @@ import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
|
||||
"github.com/filecoin-project/go-address"
|
||||
"github.com/filecoin-project/lotus/api"
|
||||
init_ "github.com/filecoin-project/lotus/chain/actors/builtin/init"
|
||||
"github.com/filecoin-project/lotus/chain/actors/builtin/reward"
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
"github.com/filecoin-project/lotus/conformance"
|
||||
"github.com/filecoin-project/specs-actors/actors/builtin"
|
||||
"github.com/ipfs/go-cid"
|
||||
"github.com/urfave/cli/v2"
|
||||
|
||||
"github.com/filecoin-project/oni/tvx/state"
|
||||
"github.com/filecoin-project/test-vectors/schema"
|
||||
|
||||
"github.com/filecoin-project/oni/tvx/state"
|
||||
)
|
||||
|
||||
var extractMsgFlags struct {
|
||||
cid string
|
||||
file string
|
||||
cid string
|
||||
file string
|
||||
retain string
|
||||
}
|
||||
|
||||
var extractMsgCmd = &cli.Command{
|
||||
@ -41,6 +48,12 @@ var extractMsgCmd = &cli.Command{
|
||||
Required: true,
|
||||
Destination: &extractMsgFlags.file,
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "state-retain",
|
||||
Usage: "state retention policy; values: 'accessed-cids' (default), 'accessed-actors'",
|
||||
Value: "accessed-actors",
|
||||
Destination: &extractMsgFlags.retain,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
@ -62,7 +75,7 @@ func runExtractMsg(c *cli.Context) error {
|
||||
return fmt.Errorf("output file required")
|
||||
}
|
||||
|
||||
mid, err := cid.Decode(extractMsgFlags.cid)
|
||||
mcid, err := cid.Decode(extractMsgFlags.cid)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -73,110 +86,112 @@ func runExtractMsg(c *cli.Context) error {
|
||||
return err
|
||||
}
|
||||
|
||||
// locate the message.
|
||||
msgInfo, err := api.StateSearchMsg(ctx, mid)
|
||||
log.Printf("locating message with CID: %s...", mcid)
|
||||
|
||||
// Locate the message.
|
||||
msgInfo, err := api.StateSearchMsg(ctx, mcid)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to locate message: %w", err)
|
||||
}
|
||||
|
||||
// Extract the serialized message.
|
||||
msg, err := api.ChainGetMessage(ctx, mid)
|
||||
log.Printf("located message at tipset %s (height: %d) with exit code: %s", msgInfo.TipSet, msgInfo.Height, msgInfo.Receipt.ExitCode)
|
||||
|
||||
// Extract the full message.
|
||||
msg, err := api.ChainGetMessage(ctx, mcid)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// create a read through store that uses ChainGetObject to fetch unknown CIDs.
|
||||
pst := state.NewProxyingStore(ctx, api)
|
||||
log.Printf("full message: %+v", msg)
|
||||
|
||||
g := state.NewSurgeon(ctx, api, pst)
|
||||
|
||||
// Get actors accessed by message.
|
||||
retain, err := g.GetAccessedActors(ctx, api, mid)
|
||||
execTs, incTs, err := findRelevantTipsets(ctx, api, msgInfo.TipSet)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
retain = append(retain, builtin.RewardActorAddr)
|
||||
retain = append(retain, builtin.BurntFundsActorAddr)
|
||||
log.Printf("message was executed in tipset: %s", execTs.Key())
|
||||
log.Printf("message was included in tipset: %s", incTs.Key())
|
||||
log.Printf("finding precursor messages...")
|
||||
|
||||
fmt.Println("accessed actors:")
|
||||
for _, k := range retain {
|
||||
fmt.Println("\t", k.String())
|
||||
}
|
||||
|
||||
// get the tipset on which this message was "executed".
|
||||
// https://github.com/filecoin-project/lotus/issues/2847
|
||||
execTs, err := api.ChainGetTipSet(ctx, msgInfo.TipSet)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// get the previous tipset, on which this message was mined.
|
||||
includedTs, err := api.ChainGetTipSet(ctx, execTs.Parents())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
neededPrecursorMsgs := make([]*types.Message, 0)
|
||||
for _, b := range includedTs.Blocks() {
|
||||
var allmsgs []*types.Message
|
||||
for _, b := range incTs.Blocks() {
|
||||
messages, err := api.ChainGetBlockMessages(ctx, b.Cid())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, other := range messages.BlsMessages {
|
||||
if other.Cid() == mid {
|
||||
break
|
||||
}
|
||||
if other.From == msg.From && other.Nonce < msg.Nonce {
|
||||
included := false
|
||||
for _, o := range neededPrecursorMsgs {
|
||||
if o.Cid() == other.Cid() {
|
||||
included = true
|
||||
}
|
||||
}
|
||||
if !included {
|
||||
neededPrecursorMsgs = append(neededPrecursorMsgs, other)
|
||||
}
|
||||
}
|
||||
|
||||
related, found, err := findMsgAndPrecursors(messages, msg)
|
||||
if err != nil {
|
||||
return fmt.Errorf("invariant failed while scanning messages in block %s: %w", b.Cid(), err)
|
||||
}
|
||||
for _, m := range messages.SecpkMessages {
|
||||
if m.Message.Cid() == mid {
|
||||
break
|
||||
}
|
||||
if m.Message.From == msg.From && m.Message.Nonce < msg.Nonce {
|
||||
included := false
|
||||
for _, o := range neededPrecursorMsgs {
|
||||
if o.Cid() == m.Message.Cid() {
|
||||
included = true
|
||||
}
|
||||
}
|
||||
if !included {
|
||||
neededPrecursorMsgs = append(neededPrecursorMsgs, &m.Message)
|
||||
}
|
||||
|
||||
if found {
|
||||
var mcids []cid.Cid
|
||||
for _, m := range related {
|
||||
mcids = append(mcids, m.Cid())
|
||||
}
|
||||
log.Printf("found message in block %s; precursors: %v", b.Cid(), mcids[:len(mcids)-1])
|
||||
allmsgs = related
|
||||
break
|
||||
}
|
||||
|
||||
log.Printf("message not found in block %s; precursors found: %d", b.Cid(), len(related))
|
||||
}
|
||||
|
||||
fmt.Println("getting the _before_ filtered state tree")
|
||||
tree, err := g.GetStateTreeRootFromTipset(includedTs.Parents())
|
||||
if allmsgs == nil {
|
||||
// Message was not found; abort.
|
||||
return fmt.Errorf("did not find a block containing the message")
|
||||
}
|
||||
|
||||
precursors := allmsgs[:len(allmsgs)-1]
|
||||
|
||||
var (
|
||||
// create a read through store that uses ChainGetObject to fetch unknown CIDs.
|
||||
pst = state.NewProxyingStores(ctx, api)
|
||||
g = state.NewSurgeon(ctx, api, pst)
|
||||
)
|
||||
|
||||
driver := conformance.NewDriver(ctx, schema.Selector{})
|
||||
|
||||
for _, pm := range neededPrecursorMsgs {
|
||||
_, tree, err = driver.ExecuteMessage(pst.Blockstore, tree, execTs.Height(), pm)
|
||||
// this is the root of the state tree we start with.
|
||||
root := incTs.ParentState()
|
||||
log.Printf("base state tree root CID: %s", root)
|
||||
|
||||
// on top of that state tree, we apply all precursors.
|
||||
log.Printf("precursors to apply: %d", len(precursors))
|
||||
for i, m := range precursors {
|
||||
log.Printf("applying precursor %d, cid: %s", i, m.Cid())
|
||||
_, root, err = driver.ExecuteMessage(pst.Blockstore, root, execTs.Height(), m)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to execute preceding message: %w", err)
|
||||
return fmt.Errorf("failed to execute precursor message: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
preroot, err := g.GetMaskedStateTree(tree, retain)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
var (
|
||||
preroot cid.Cid
|
||||
postroot cid.Cid
|
||||
)
|
||||
|
||||
_, postroot, err := driver.ExecuteMessage(pst.Blockstore, preroot, execTs.Height(), msg)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to execute message: %w", err)
|
||||
if extractMsgFlags.retain == "accessed-actors" {
|
||||
log.Printf("calculating accessed actors...")
|
||||
// get actors accessed by message.
|
||||
retain, err := g.GetAccessedActors(ctx, api, mcid)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to calculate accessed actors: %w", err)
|
||||
}
|
||||
// also append the reward actor and the burnt funds actor.
|
||||
retain = append(retain, reward.Address, builtin.BurntFundsActorAddr, init_.Address)
|
||||
log.Printf("calculated accessed actors: %v", retain)
|
||||
|
||||
// get the masked state tree from the root,
|
||||
preroot, err = g.GetMaskedStateTree(root, retain)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, postroot, err = driver.ExecuteMessage(pst.Blockstore, preroot, execTs.Height(), msg)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to execute message: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
msgBytes, err := msg.Serialize()
|
||||
@ -250,3 +265,64 @@ func runExtractMsg(c *cli.Context) error {
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func findRelevantTipsets(ctx context.Context, api api.FullNode, execTsk types.TipSetKey) (execTs *types.TipSet, incTs *types.TipSet, err error) {
|
||||
// get the tipset on which this message was "executed" on.
|
||||
// https://github.com/filecoin-project/lotus/issues/2847
|
||||
execTs, err = api.ChainGetTipSet(ctx, execTsk)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
// get the previous tipset, on which this message was mined,
|
||||
// i.e. included on-chain.
|
||||
incTs, err = api.ChainGetTipSet(ctx, execTs.Parents())
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
return execTs, incTs, nil
|
||||
}
|
||||
|
||||
// findMsgAndPrecursors scans the messages in a block to locate the supplied
|
||||
// message, looking into the BLS or SECP section depending on the sender's
|
||||
// address type.
|
||||
//
|
||||
// It returns any precursors (if they exist), and the found message (if found),
|
||||
// in a slice.
|
||||
//
|
||||
// It also returns a boolean indicating whether the message was actually found.
|
||||
//
|
||||
// This function also asserts invariants, and if those fail, it returns an error.
|
||||
func findMsgAndPrecursors(messages *api.BlockMessages, target *types.Message) (related []*types.Message, found bool, err error) {
|
||||
// Decide which block of messages to process, depending on whether the
|
||||
// sender is a BLS or a SECP account.
|
||||
input := messages.BlsMessages
|
||||
if senderKind := target.From.Protocol(); senderKind == address.SECP256K1 {
|
||||
input = make([]*types.Message, 0, len(messages.SecpkMessages))
|
||||
for _, sm := range messages.SecpkMessages {
|
||||
input = append(input, &sm.Message)
|
||||
}
|
||||
}
|
||||
|
||||
for _, other := range input {
|
||||
if other.From != target.From {
|
||||
continue
|
||||
}
|
||||
|
||||
// this message is from the same sender, so it's related.
|
||||
related = append(related, other)
|
||||
|
||||
if other.Nonce > target.Nonce {
|
||||
return nil, false, fmt.Errorf("a message with nonce higher than the target was found before the target; offending mcid: %s", other.Cid())
|
||||
}
|
||||
|
||||
// this message is the target; we're done.
|
||||
if other.Cid() == target.Cid() {
|
||||
return related, true, nil
|
||||
}
|
||||
}
|
||||
|
||||
// this could happen because a block contained related messages, but not
|
||||
// the target (that is, messages with a lower nonce, but ultimately not the
|
||||
// target).
|
||||
return related, false, nil
|
||||
}
|
||||
|
@ -3,10 +3,11 @@ module github.com/filecoin-project/oni/tvx
|
||||
go 1.14
|
||||
|
||||
require (
|
||||
github.com/fatih/color v1.8.0
|
||||
github.com/filecoin-project/go-address v0.0.3
|
||||
github.com/filecoin-project/go-state-types v0.0.0-20200911004822-964d6c679cfc
|
||||
github.com/filecoin-project/lotus v0.7.2
|
||||
github.com/filecoin-project/specs-actors v0.9.10
|
||||
github.com/filecoin-project/lotus v0.8.0
|
||||
github.com/filecoin-project/specs-actors v0.9.11
|
||||
github.com/filecoin-project/test-vectors/schema v0.0.1
|
||||
github.com/ipfs/go-block-format v0.0.2
|
||||
github.com/ipfs/go-blockservice v0.1.4-0.20200624145336-a978cec6e834
|
||||
|
22
tvx/go.sum
22
tvx/go.sum
@ -205,12 +205,12 @@ github.com/filecoin-project/go-cbor-util v0.0.0-20191219014500-08c40a1e63a2 h1:a
|
||||
github.com/filecoin-project/go-cbor-util v0.0.0-20191219014500-08c40a1e63a2/go.mod h1:pqTiPHobNkOVM5thSRsHYjyQfq7O5QSCMhvuu9JoDlg=
|
||||
github.com/filecoin-project/go-crypto v0.0.0-20191218222705-effae4ea9f03 h1:2pMXdBnCiXjfCYx/hLqFxccPoqsSveQFxVLvNxy9bus=
|
||||
github.com/filecoin-project/go-crypto v0.0.0-20191218222705-effae4ea9f03/go.mod h1:+viYnvGtUTgJRdy6oaeF4MTFKAfatX071MPDPBL11EQ=
|
||||
github.com/filecoin-project/go-data-transfer v0.6.5 h1:oP20la8Z0CLrw0uqvt6xVgw6rOevZeGJ9GNQeC0OCSU=
|
||||
github.com/filecoin-project/go-data-transfer v0.6.5/go.mod h1:I9Ylb/UiZyqnI41wUoCXq/le0nDLhlwpFQCtNPxEPOA=
|
||||
github.com/filecoin-project/go-data-transfer v0.6.6 h1:2TccLSxPYJENcYRdov2WvpTvQ1qUMrPkWe8sBrfj36g=
|
||||
github.com/filecoin-project/go-data-transfer v0.6.6/go.mod h1:C++k1U6+jMQODOaen5OPDo9XQbth9Yq3ie94vNjBJbk=
|
||||
github.com/filecoin-project/go-fil-commcid v0.0.0-20200716160307-8f644712406f h1:GxJzR3oRIMTPtpZ0b7QF8FKPK6/iPAc7trhlL5k/g+s=
|
||||
github.com/filecoin-project/go-fil-commcid v0.0.0-20200716160307-8f644712406f/go.mod h1:Eaox7Hvus1JgPrL5+M3+h7aSPHc0cVqpSxA+TxIEpZQ=
|
||||
github.com/filecoin-project/go-fil-markets v0.6.2 h1:9Z57KeaQSa1liCmT1pH6SIjrn9mGTDFJXmR2WQVuaiY=
|
||||
github.com/filecoin-project/go-fil-markets v0.6.2/go.mod h1:wtN4Hc/1hoVCpWhSWYxwUxH3PQtjSkWWuC1nQjiIWog=
|
||||
github.com/filecoin-project/go-fil-markets v0.6.3 h1:3kTxfquGvk3zQY+hJH1kEA28tRQ47phqSRqOI4+YcQM=
|
||||
github.com/filecoin-project/go-fil-markets v0.6.3/go.mod h1:Ug1yhGhzTYC6qrpKsR2QpU8QRCeBpwkTA9RICVKuOMM=
|
||||
github.com/filecoin-project/go-hamt-ipld v0.1.5 h1:uoXrKbCQZ49OHpsTCkrThPNelC4W3LPEk0OrS/ytIBM=
|
||||
github.com/filecoin-project/go-hamt-ipld v0.1.5/go.mod h1:6Is+ONR5Cd5R6XZoCse1CWaXZc0Hdb/JeX+EQCQzX24=
|
||||
github.com/filecoin-project/go-jsonrpc v0.1.2-0.20200822201400-474f4fdccc52 h1:FXtCp0ybqdQL9knb3OGDpkNTaBbPxgkqPeWKotUwkH0=
|
||||
@ -233,12 +233,12 @@ github.com/filecoin-project/go-statestore v0.1.0 h1:t56reH59843TwXHkMcwyuayStBIi
|
||||
github.com/filecoin-project/go-statestore v0.1.0/go.mod h1:LFc9hD+fRxPqiHiaqUEZOinUJB4WARkRfNl10O7kTnI=
|
||||
github.com/filecoin-project/go-storedcounter v0.0.0-20200421200003-1c99c62e8a5b h1:fkRZSPrYpk42PV3/lIXiL0LHetxde7vyYYvSsttQtfg=
|
||||
github.com/filecoin-project/go-storedcounter v0.0.0-20200421200003-1c99c62e8a5b/go.mod h1:Q0GQOBtKf1oE10eSXSlhN45kDBdGvEcVOqMiffqX+N8=
|
||||
github.com/filecoin-project/lotus v0.7.2 h1:ouCa4ZL1DwLZV+HcT4D+om4wM3T/wYdspj7vKR9Cv8Y=
|
||||
github.com/filecoin-project/lotus v0.7.2/go.mod h1:lSaELDZAkZ5vgGn2+OTvSHVxjxi2en1agfh6ytl2Jbw=
|
||||
github.com/filecoin-project/lotus v0.8.0 h1:V6wVAYoFyuvJ10vZ5eGwxs/QatzjEL2yjliVRTWoC0g=
|
||||
github.com/filecoin-project/lotus v0.8.0/go.mod h1:31qmN62Dm8APRHXmW/hMbqKcrkoPVISERSX7RGQQbOs=
|
||||
github.com/filecoin-project/specs-actors v0.9.4/go.mod h1:BStZQzx5x7TmCkLv0Bpa07U6cPKol6fd3w9KjMPZ6Z4=
|
||||
github.com/filecoin-project/specs-actors v0.9.7/go.mod h1:wM2z+kwqYgXn5Z7scV1YHLyd1Q1cy0R8HfTIWQ0BFGU=
|
||||
github.com/filecoin-project/specs-actors v0.9.10 h1:gU0TrRhgkCsBEOP42sGDE7RQuR0Cov9hJhBqq+RJmjU=
|
||||
github.com/filecoin-project/specs-actors v0.9.10/go.mod h1:czlvLQGEX0fjLLfdNHD7xLymy6L3n7aQzRWzsYGf+ys=
|
||||
github.com/filecoin-project/specs-actors v0.9.11 h1:TnpG7HAeiUrfj0mJM7UaPW0P2137H62RGof7ftT5Mas=
|
||||
github.com/filecoin-project/specs-actors v0.9.11/go.mod h1:czlvLQGEX0fjLLfdNHD7xLymy6L3n7aQzRWzsYGf+ys=
|
||||
github.com/filecoin-project/specs-storage v0.1.1-0.20200907031224-ed2e5cd13796 h1:dJsTPWpG2pcTeojO2pyn0c6l+x/3MZYCBgo/9d11JEk=
|
||||
github.com/filecoin-project/specs-storage v0.1.1-0.20200907031224-ed2e5cd13796/go.mod h1:nJRRM7Aa9XVvygr3W9k6xGF46RWzr2zxF/iGoAIfA/g=
|
||||
github.com/filecoin-project/test-vectors/schema v0.0.1 h1:5fNF76nl4qolEvcIsjc0kUADlTMVHO73tW4kXXPnsus=
|
||||
@ -470,8 +470,8 @@ github.com/ipfs/go-filestore v1.0.0/go.mod h1:/XOCuNtIe2f1YPbiXdYvD0BKLA0JR1MgPi
|
||||
github.com/ipfs/go-fs-lock v0.0.6 h1:sn3TWwNVQqSeNjlWy6zQ1uUGAZrV3hPOyEA6y1/N2a0=
|
||||
github.com/ipfs/go-fs-lock v0.0.6/go.mod h1:OTR+Rj9sHiRubJh3dRhD15Juhd/+w6VPOY28L7zESmM=
|
||||
github.com/ipfs/go-graphsync v0.1.0/go.mod h1:jMXfqIEDFukLPZHqDPp8tJMbHO9Rmeb9CEGevngQbmE=
|
||||
github.com/ipfs/go-graphsync v0.2.0 h1:x94MvHLNuRwBlZzVal7tR1RYK7T7H6bqQLPopxDbIF0=
|
||||
github.com/ipfs/go-graphsync v0.2.0/go.mod h1:gEBvJUNelzMkaRPJTpg/jaKN4AQW/7wDWu0K92D8o10=
|
||||
github.com/ipfs/go-graphsync v0.2.1 h1:MdehhqBSuTI2LARfKLkpYnt0mUrqHs/mtuDnESXHBfU=
|
||||
github.com/ipfs/go-graphsync v0.2.1/go.mod h1:gEBvJUNelzMkaRPJTpg/jaKN4AQW/7wDWu0K92D8o10=
|
||||
github.com/ipfs/go-hamt-ipld v0.1.1 h1:0IQdvwnAAUKmDE+PMJa5y1QiwOPHpI9+eAbQEEEYthk=
|
||||
github.com/ipfs/go-hamt-ipld v0.1.1/go.mod h1:1EZCr2v0jlCnhpa+aZ0JZYp8Tt2w16+JJOAVz17YcDk=
|
||||
github.com/ipfs/go-ipfs-blockstore v0.0.1/go.mod h1:d3WClOmRQKFnJ0Jz/jj/zmksX0ma1gROTlovZKBmN08=
|
||||
@ -1262,6 +1262,7 @@ github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5
|
||||
github.com/stretchr/testify v1.6.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0=
|
||||
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/supranational/blst v0.1.2-alpha.1 h1:v0UqVlvbRNZIaSeMPr+T01kvTUq1h0EZuZ6gnDR1Mlg=
|
||||
github.com/supranational/blst v0.1.2-alpha.1/go.mod h1:jZJtfjgudtNl4en1tzwPIV3KjUnQUvG3/j+w+fVonLw=
|
||||
github.com/syndtr/goleveldb v1.0.0 h1:fBdIW9lB4Iz0n9khmH8w27SJ3QEJ7+IgjPEwGSZiFdE=
|
||||
github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ=
|
||||
@ -1732,6 +1733,7 @@ honnef.co/go/tools v0.0.1-2020.1.3 h1:sXmLre5bzIR6ypkjXCDI3jHPssRhc8KD/Ome589sc3
|
||||
honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
|
||||
howett.net/plist v0.0.0-20181124034731-591f970eefbb h1:jhnBjNi9UFpfpl8YZhA9CrOqpnJdvzuiHsl/dnxl11M=
|
||||
howett.net/plist v0.0.0-20181124034731-591f970eefbb/go.mod h1:vMygbs4qMhSZSc4lCUl2OEE+rDiIIJAIdR4m7MiMcm0=
|
||||
launchpad.net/gocheck v0.0.0-20140225173054-000000000087 h1:Izowp2XBH6Ya6rv+hqbceQyw/gSGoXfH/UPoTGduL54=
|
||||
launchpad.net/gocheck v0.0.0-20140225173054-000000000087/go.mod h1:hj7XX3B/0A+80Vse0e+BUHsHMTEhd0O4cpUHr/e/BUM=
|
||||
modernc.org/cc v1.0.0 h1:nPibNuDEx6tvYrUAtvDTTw98rx5juGsa5zuDnKwEEQQ=
|
||||
modernc.org/cc v1.0.0/go.mod h1:1Sk4//wdnYJiUIxnW8ddKpaOJCF37yAdqYnkxUpaYxw=
|
||||
|
@ -42,7 +42,7 @@ func runListAccessed(c *cli.Context) error {
|
||||
return err
|
||||
}
|
||||
|
||||
rtst := state.NewProxyingStore(ctx, node)
|
||||
rtst := state.NewProxyingStores(ctx, node)
|
||||
|
||||
sg := state.NewSurgeon(ctx, node, rtst)
|
||||
|
||||
|
@ -2,8 +2,10 @@ package state
|
||||
|
||||
import (
|
||||
"context"
|
||||
"log"
|
||||
"sync"
|
||||
|
||||
"github.com/fatih/color"
|
||||
"github.com/filecoin-project/lotus/api"
|
||||
"github.com/filecoin-project/lotus/lib/blockstore"
|
||||
|
||||
@ -69,7 +71,7 @@ func (pb *proxyingBlockstore) Get(cid cid.Cid) (blocks.Block, error) {
|
||||
}
|
||||
pb.lock.RUnlock()
|
||||
|
||||
// fmt.Printf("fetching cid via rpc: %v\n", cid)
|
||||
log.Println(color.CyanString("fetching cid via rpc: %v", cid))
|
||||
item, err := pb.api.ChainReadObj(pb.ctx, cid)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -93,9 +95,9 @@ func (pb *proxyingBlockstore) SetOnline(online bool) {
|
||||
pb.online = online
|
||||
}
|
||||
|
||||
// NewProxyingStore is a Stores that proxies get requests for unknown CIDs
|
||||
// NewProxyingStores is a Stores that proxies get requests for unknown CIDs
|
||||
// to a Filecoin node, via the ChainReadObj RPC.
|
||||
func NewProxyingStore(ctx context.Context, api api.FullNode) *Stores {
|
||||
func NewProxyingStores(ctx context.Context, api api.FullNode) *Stores {
|
||||
ds := ds.NewMapDatastore()
|
||||
|
||||
bs := &proxyingBlockstore{
|
||||
|
@ -9,12 +9,10 @@ import (
|
||||
"github.com/filecoin-project/go-address"
|
||||
"github.com/filecoin-project/go-state-types/abi"
|
||||
"github.com/filecoin-project/lotus/api"
|
||||
"github.com/filecoin-project/lotus/chain/actors/builtin"
|
||||
init_ "github.com/filecoin-project/lotus/chain/actors/builtin/init"
|
||||
"github.com/filecoin-project/lotus/chain/state"
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
"github.com/filecoin-project/lotus/chain/vm"
|
||||
|
||||
"github.com/ipfs/go-cid"
|
||||
"github.com/ipfs/go-ipld-format"
|
||||
"github.com/ipld/go-car"
|
||||
@ -54,17 +52,12 @@ func (sg *Surgeon) GetStateTreeRootFromTipset(tsk types.TipSetKey) (cid.Cid, err
|
||||
// other system actors like the power actor and the market actor.
|
||||
func (sg *Surgeon) GetMaskedStateTree(previousRoot cid.Cid, retain []address.Address) (cid.Cid, error) {
|
||||
// TODO: this will need to be parameterized on network version.
|
||||
stateTree, err := state.NewStateTree(sg.stores.CBORStore, builtin.Version0)
|
||||
st, err := state.LoadStateTree(sg.stores.CBORStore, previousRoot)
|
||||
if err != nil {
|
||||
return cid.Undef, err
|
||||
}
|
||||
|
||||
initActor, initState, err := sg.loadInitActor(previousRoot)
|
||||
if err != nil {
|
||||
return cid.Undef, err
|
||||
}
|
||||
|
||||
resolved, err := sg.resolveAddresses(retain, initState)
|
||||
initActor, initState, err := sg.loadInitActor(st)
|
||||
if err != nil {
|
||||
return cid.Undef, err
|
||||
}
|
||||
@ -74,17 +67,23 @@ func (sg *Surgeon) GetMaskedStateTree(previousRoot cid.Cid, retain []address.Add
|
||||
return cid.Undef, err
|
||||
}
|
||||
|
||||
err = sg.saveInitActor(initActor, initState, stateTree)
|
||||
err = sg.saveInitActor(initActor, initState, st)
|
||||
if err != nil {
|
||||
return cid.Undef, err
|
||||
}
|
||||
|
||||
err = sg.pluckActorStates(previousRoot, resolved, stateTree)
|
||||
// resolve all addresses to ID addresses.
|
||||
resolved, err := sg.resolveAddresses(retain, initState)
|
||||
if err != nil {
|
||||
return cid.Undef, err
|
||||
}
|
||||
|
||||
root, err := stateTree.Flush(sg.ctx)
|
||||
st, err = sg.transplantActors(st, resolved)
|
||||
if err != nil {
|
||||
return cid.Undef, err
|
||||
}
|
||||
|
||||
root, err := st.Flush(sg.ctx)
|
||||
if err != nil {
|
||||
return cid.Undef, err
|
||||
}
|
||||
@ -120,6 +119,7 @@ func (sg *Surgeon) GetAccessedActors(ctx context.Context, a api.FullNode, mid ci
|
||||
}
|
||||
|
||||
accessed := make(map[address.Address]struct{})
|
||||
|
||||
var recur func(trace *types.ExecutionTrace)
|
||||
recur = func(trace *types.ExecutionTrace) {
|
||||
accessed[trace.Msg.To] = struct{}{}
|
||||
@ -128,7 +128,6 @@ func (sg *Surgeon) GetAccessedActors(ctx context.Context, a api.FullNode, mid ci
|
||||
recur(&s)
|
||||
}
|
||||
}
|
||||
|
||||
recur(&trace.ExecutionTrace)
|
||||
|
||||
ret := make([]address.Address, 0, len(accessed))
|
||||
@ -154,35 +153,41 @@ func (sg *Surgeon) WriteCAR(w io.Writer, roots ...cid.Cid) error {
|
||||
return car.WriteCarWithWalker(sg.ctx, sg.stores.DAGService, roots, w, carWalkFn)
|
||||
}
|
||||
|
||||
// pluckActorStates plucks the state from the supplied actors at the given
|
||||
// transplantActors plucks the state from the supplied actors at the given
|
||||
// tipset, and places it into the supplied state map.
|
||||
func (sg *Surgeon) pluckActorStates(stateRoot cid.Cid, pluck []address.Address, st *state.StateTree) error {
|
||||
func (sg *Surgeon) transplantActors(src *state.StateTree, pluck []address.Address) (*state.StateTree, error) {
|
||||
log.Printf("transplanting actor states: %v", pluck)
|
||||
|
||||
dst, err := state.NewStateTree(sg.stores.CBORStore, src.Version())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, a := range pluck {
|
||||
actor, err := st.GetActor(a)
|
||||
actor, err := src.GetActor(a)
|
||||
if err != nil {
|
||||
continue
|
||||
//return fmt.Errorf("get actor %s failed: %w", a, err)
|
||||
return nil, fmt.Errorf("get actor %s failed: %w", a, err)
|
||||
}
|
||||
|
||||
err = st.SetActor(a, actor)
|
||||
err = dst.SetActor(a, actor)
|
||||
if err != nil {
|
||||
return err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// recursive copy of the actor state so we can
|
||||
err = vm.Copy(sg.stores.Blockstore, sg.stores.Blockstore, actor.Head)
|
||||
// recursive copy of the actor state.
|
||||
err = vm.Copy(context.TODO(), sg.stores.Blockstore, sg.stores.Blockstore, actor.Head)
|
||||
if err != nil {
|
||||
return err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
actorState, err := sg.api.ChainReadObj(sg.ctx, actor.Head)
|
||||
if err != nil {
|
||||
return err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
cid, err := sg.stores.CBORStore.Put(sg.ctx, &cbg.Deferred{Raw: actorState})
|
||||
if err != nil {
|
||||
return err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if cid != actor.Head {
|
||||
@ -190,11 +195,11 @@ func (sg *Surgeon) pluckActorStates(stateRoot cid.Cid, pluck []address.Address,
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
return dst, nil
|
||||
}
|
||||
|
||||
// saveInitActor saves the state of the init actor to the provided state map.
|
||||
func (sg *Surgeon) saveInitActor(initActor *types.Actor, initState init_.State, stateMap *state.StateTree) error {
|
||||
func (sg *Surgeon) saveInitActor(initActor *types.Actor, initState init_.State, st *state.StateTree) error {
|
||||
log.Printf("saving init actor into state tree")
|
||||
|
||||
// Store the state of the init actor.
|
||||
@ -205,12 +210,12 @@ func (sg *Surgeon) saveInitActor(initActor *types.Actor, initState init_.State,
|
||||
actor := *initActor
|
||||
actor.Head = cid
|
||||
|
||||
err = stateMap.SetActor(init_.Address, &actor)
|
||||
err = st.SetActor(init_.Address, &actor)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
cid, _ = stateMap.Flush(sg.ctx)
|
||||
cid, _ = st.Flush(sg.ctx)
|
||||
log.Printf("saved init actor into state tree; new root: %s", cid)
|
||||
return nil
|
||||
}
|
||||
@ -261,14 +266,7 @@ func (sg *Surgeon) resolveAddresses(orig []address.Address, ist init_.State) (re
|
||||
}
|
||||
|
||||
// loadInitActor loads the init actor state from a given tipset.
|
||||
func (sg *Surgeon) loadInitActor(stateRoot cid.Cid) (*types.Actor, init_.State, error) {
|
||||
log.Printf("loading the init actor for root: %s", stateRoot)
|
||||
|
||||
st, err := state.LoadStateTree(sg.stores.CBORStore, stateRoot)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
func (sg *Surgeon) loadInitActor(st *state.StateTree) (*types.Actor, init_.State, error) {
|
||||
actor, err := st.GetActor(init_.Address)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
|
Loading…
Reference in New Issue
Block a user