Merge pull request #1184 from filecoin-project/feat/chain-bisect
chain: bisect cmd
This commit is contained in:
commit
f837cb5513
@ -34,31 +34,31 @@ type EPostProof struct {
|
||||
}
|
||||
|
||||
type BlockHeader struct {
|
||||
Miner address.Address
|
||||
Miner address.Address // 0
|
||||
|
||||
Ticket *Ticket
|
||||
Ticket *Ticket // 1
|
||||
|
||||
EPostProof EPostProof
|
||||
EPostProof EPostProof // 2
|
||||
|
||||
Parents []cid.Cid
|
||||
Parents []cid.Cid // 3
|
||||
|
||||
ParentWeight BigInt
|
||||
ParentWeight BigInt // 4
|
||||
|
||||
Height uint64
|
||||
Height uint64 // 5
|
||||
|
||||
ParentStateRoot cid.Cid
|
||||
ParentStateRoot cid.Cid // 6
|
||||
|
||||
ParentMessageReceipts cid.Cid
|
||||
ParentMessageReceipts cid.Cid // 7
|
||||
|
||||
Messages cid.Cid
|
||||
Messages cid.Cid // 8
|
||||
|
||||
BLSAggregate Signature
|
||||
BLSAggregate Signature // 9
|
||||
|
||||
Timestamp uint64
|
||||
Timestamp uint64 // 10
|
||||
|
||||
BlockSig *Signature
|
||||
BlockSig *Signature // 11
|
||||
|
||||
ForkSignaling uint64
|
||||
ForkSignaling uint64 // 12
|
||||
}
|
||||
|
||||
func (b *BlockHeader) ToStorageBlock() (block.Block, error) {
|
||||
|
109
cli/chain.go
109
cli/chain.go
@ -1,10 +1,13 @@
|
||||
package cli
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
@ -28,6 +31,7 @@ var chainCmd = &cli.Command{
|
||||
chainSetHeadCmd,
|
||||
chainListCmd,
|
||||
chainGetCmd,
|
||||
chainBisectCmd,
|
||||
chainExportCmd,
|
||||
slashConsensusFault,
|
||||
},
|
||||
@ -402,6 +406,111 @@ func printTipSet(format string, ts *types.TipSet) {
|
||||
fmt.Println(format)
|
||||
}
|
||||
|
||||
var chainBisectCmd = &cli.Command{
|
||||
Name: "bisect",
|
||||
Usage: "bisect chain for an event",
|
||||
Description: `Bisect the chain state tree:
|
||||
|
||||
lotus chain bisect [min height] [max height] '1/2/3/state/path' 'shell command' 'args'
|
||||
|
||||
Returns the first tipset in which condition is true
|
||||
v
|
||||
[start] FFFFFFFTTT [end]
|
||||
|
||||
Example: find height at which deal ID 100 000 appeared
|
||||
- lotus chain bisect 1 32000 '@Ha:t03/1' jq -e '.[2] > 100000'
|
||||
|
||||
For special path elements see 'chain get' help
|
||||
`,
|
||||
Action: func(cctx *cli.Context) error {
|
||||
api, closer, err := GetFullNodeAPI(cctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer closer()
|
||||
ctx := ReqContext(cctx)
|
||||
|
||||
if cctx.Args().Len() < 4 {
|
||||
return xerrors.New("need at least 4 args")
|
||||
}
|
||||
|
||||
start, err := strconv.ParseUint(cctx.Args().Get(0), 10, 64)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
end, err := strconv.ParseUint(cctx.Args().Get(1), 10, 64)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
subPath := cctx.Args().Get(2)
|
||||
|
||||
highest, err := api.ChainGetTipSetByHeight(ctx, end, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
prev := highest.Height()
|
||||
|
||||
for {
|
||||
mid := (start + end) / 2
|
||||
if end - start == 1 {
|
||||
mid = end
|
||||
start = end
|
||||
}
|
||||
|
||||
midTs, err := api.ChainGetTipSetByHeight(ctx, mid, highest)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
path := "/ipld/" + midTs.ParentState().String() + "/" + subPath
|
||||
fmt.Printf("* Testing %d (%d - %d) (%s): ", mid, start, end, path)
|
||||
|
||||
nd, err := api.ChainGetNode(ctx, path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
b, err := json.MarshalIndent(nd, "", "\t")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
cmd := exec.CommandContext(ctx, cctx.Args().Get(3), cctx.Args().Slice()[4:]...)
|
||||
cmd.Stdin = bytes.NewReader(b)
|
||||
|
||||
var out bytes.Buffer
|
||||
cmd.Stdout = &out
|
||||
|
||||
switch cmd.Run().(type) {
|
||||
case nil:
|
||||
// it's lower
|
||||
end = mid
|
||||
highest = midTs
|
||||
fmt.Println("true")
|
||||
case *exec.ExitError:
|
||||
start = mid
|
||||
fmt.Println("false")
|
||||
default:
|
||||
return err
|
||||
}
|
||||
|
||||
if start == end {
|
||||
if strings.TrimSpace(out.String()) == "true" {
|
||||
fmt.Println(midTs.Height())
|
||||
} else {
|
||||
fmt.Println(prev)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
prev = mid
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
var chainExportCmd = &cli.Command{
|
||||
Name: "export",
|
||||
Usage: "export chain to a car file",
|
||||
|
Loading…
Reference in New Issue
Block a user