chain: bisect cmd
This commit is contained in:
parent
b42e481600
commit
de5577ca70
@ -34,31 +34,31 @@ type EPostProof struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type BlockHeader 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) {
|
func (b *BlockHeader) ToStorageBlock() (block.Block, error) {
|
||||||
|
111
cli/chain.go
111
cli/chain.go
@ -1,10 +1,13 @@
|
|||||||
package cli
|
package cli
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
|
"os/exec"
|
||||||
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@ -28,6 +31,7 @@ var chainCmd = &cli.Command{
|
|||||||
chainSetHeadCmd,
|
chainSetHeadCmd,
|
||||||
chainListCmd,
|
chainListCmd,
|
||||||
chainGetCmd,
|
chainGetCmd,
|
||||||
|
chainBisectCmd,
|
||||||
chainExportCmd,
|
chainExportCmd,
|
||||||
slashConsensusFault,
|
slashConsensusFault,
|
||||||
},
|
},
|
||||||
@ -394,6 +398,113 @@ func printTipSet(format string, ts *types.TipSet) {
|
|||||||
fmt.Println(format)
|
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' 'jq script'
|
||||||
|
|
||||||
|
Returns the first tipset in which jq 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' '.[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 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)
|
||||||
|
jqs := cctx.Args().Get(3)
|
||||||
|
|
||||||
|
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, "jq", jqs)
|
||||||
|
cmd.Stdin = bytes.NewReader(b)
|
||||||
|
|
||||||
|
var out bytes.Buffer
|
||||||
|
cmd.Stdout = &out
|
||||||
|
|
||||||
|
if err := cmd.Run(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if strings.TrimSpace(out.String()) == "true" {
|
||||||
|
fmt.Println("true")
|
||||||
|
// it's lower
|
||||||
|
end = mid
|
||||||
|
highest = midTs
|
||||||
|
} else {
|
||||||
|
fmt.Println("false")
|
||||||
|
start = mid
|
||||||
|
}
|
||||||
|
|
||||||
|
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{
|
var chainExportCmd = &cli.Command{
|
||||||
Name: "export",
|
Name: "export",
|
||||||
Usage: "export chain to a car file",
|
Usage: "export chain to a car file",
|
||||||
|
Loading…
Reference in New Issue
Block a user