Skip to content

Commit 197ca86

Browse files
authored
bug fix starting from 1 when initializing tree (#52)
* bug fix starting from 1 when initializing tree * change workingtree start leaf count * change workingtree start leaf count in force * print outputroot * error logs
1 parent dcae51a commit 197ca86

File tree

6 files changed

+250
-30
lines changed

6 files changed

+250
-30
lines changed

challenger/child/withdraw.go

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -47,12 +47,11 @@ func (ch *Child) handleInitiateWithdrawal(l2Sequence uint64, from string, to str
4747
}
4848

4949
func (ch *Child) prepareTree(blockHeight int64) error {
50-
if ch.InitializeTree(blockHeight) {
51-
return nil
52-
}
53-
5450
err := ch.Merkle().LoadWorkingTree(types.MustInt64ToUint64(blockHeight - 1))
5551
if err == dbtypes.ErrNotFound {
52+
if ch.InitializeTree(blockHeight) {
53+
return nil
54+
}
5655
// must not happened
5756
panic(fmt.Errorf("working tree not found at height: %d, current: %d", blockHeight-1, blockHeight))
5857
} else if err != nil {

cmd/opinitd/db.go

Lines changed: 57 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,32 @@
11
package main
22

33
import (
4+
"context"
45
"fmt"
6+
"time"
57

68
"github.com/initia-labs/opinit-bots/bot"
79
bottypes "github.com/initia-labs/opinit-bots/bot/types"
810
"github.com/initia-labs/opinit-bots/db"
911
"github.com/initia-labs/opinit-bots/executor"
12+
executortypes "github.com/initia-labs/opinit-bots/executor/types"
13+
"github.com/initia-labs/opinit-bots/node/rpcclient"
14+
"github.com/initia-labs/opinit-bots/provider/child"
15+
"github.com/initia-labs/opinit-bots/types"
1016
"github.com/spf13/cobra"
1117
)
1218

13-
// migration015Cmd handles the one-time migration of withdrawal data for v0.1.5
19+
// migrationCmd handles the one-time migration of withdrawal data for v0.1.5, v0.1.9
1420
// TODO: Remove this command in the future
15-
func migration015Cmd(ctx *cmdContext) *cobra.Command {
21+
func migrationCmd(ctx *cmdContext) *cobra.Command {
1622
cmd := &cobra.Command{
1723
Use: "migrate",
1824
Args: cobra.ExactArgs(1),
1925
Short: "Run database migrations",
2026
Long: `Run database migrations
2127
v0.1.5: Store the sequence number so that it can be accessed by address
28+
v0.1.9-1: Delete finalized trees and create new finalized trees from working trees
29+
v0.1.9-2: Fill block hash of finalized tree
2230
`,
2331
RunE: func(cmd *cobra.Command, args []string) error {
2432
version := args[0]
@@ -30,10 +38,57 @@ v0.1.5: Store the sequence number so that it can be accessed by address
3038
return err
3139
}
3240
return executor.Migration015(db)
41+
case "v0.1.9-1":
42+
// Run migration for v0.1.9-1
43+
db, err := db.NewDB(bot.GetDBPath(ctx.homePath, bottypes.BotTypeExecutor))
44+
if err != nil {
45+
return err
46+
}
47+
return executor.Migration0191(db)
48+
case "v0.1.9-2":
49+
// Run migration for v0.1.9-2
50+
db, err := db.NewDB(bot.GetDBPath(ctx.homePath, bottypes.BotTypeExecutor))
51+
if err != nil {
52+
return err
53+
}
54+
cmdCtx, done := context.WithCancel(cmd.Context())
55+
gracefulShutdown(done)
56+
interval, err := cmd.Flags().GetDuration(flagPollingInterval)
57+
if err != nil {
58+
return err
59+
}
60+
cmdCtx = types.WithPollingInterval(cmdCtx, interval)
61+
62+
configPath, err := getConfigPath(cmd, ctx.homePath, string(bottypes.BotTypeExecutor))
63+
if err != nil {
64+
return err
65+
}
66+
67+
cfg := &executortypes.Config{}
68+
err = bot.LoadJsonConfig(configPath, cfg)
69+
if err != nil {
70+
return err
71+
}
72+
73+
l2Config := cfg.L2NodeConfig(ctx.homePath)
74+
broadcasterConfig := l2Config.BroadcasterConfig
75+
cdc, _, err := child.GetCodec(broadcasterConfig.Bech32Prefix)
76+
if err != nil {
77+
return err
78+
}
79+
80+
rpcClient, err := rpcclient.NewRPCClient(cdc, l2Config.RPC)
81+
if err != nil {
82+
return err
83+
}
84+
85+
return executor.Migration0192(cmdCtx, db, rpcClient)
3386
default:
3487
return fmt.Errorf("unknown migration version: %s", version)
3588
}
3689
},
3790
}
91+
cmd = configFlag(ctx.v, cmd)
92+
cmd.Flags().Duration(flagPollingInterval, 100*time.Millisecond, "Polling interval in milliseconds")
3893
return cmd
3994
}

cmd/opinitd/root.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ func NewRootCmd() *cobra.Command {
4848
resetDBCmd(ctx),
4949
resetHeightsCmd(ctx),
5050
resetHeightCmd(ctx),
51-
migration015Cmd(ctx),
51+
migrationCmd(ctx),
5252
txCmd(ctx),
5353
version.NewVersionCommand(),
5454
)

executor/child/withdraw.go

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -63,12 +63,11 @@ func (ch *Child) handleInitiateWithdrawal(l2Sequence uint64, from string, to str
6363
}
6464

6565
func (ch *Child) prepareTree(blockHeight int64) error {
66-
if ch.InitializeTree(blockHeight) {
67-
return nil
68-
}
69-
7066
err := ch.Merkle().LoadWorkingTree(types.MustInt64ToUint64(blockHeight) - 1)
7167
if err == dbtypes.ErrNotFound {
68+
if ch.InitializeTree(blockHeight) {
69+
return nil
70+
}
7271
// must not happened
7372
panic(fmt.Errorf("working tree not found at height: %d, current: %d", blockHeight-1, blockHeight))
7473
} else if err != nil {

executor/db.go

Lines changed: 165 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,19 @@
11
package executor
22

33
import (
4+
"context"
5+
"encoding/base64"
46
"encoding/json"
57
"fmt"
8+
"math/bits"
9+
"time"
610

11+
ophosttypes "github.com/initia-labs/OPinit/x/ophost/types"
712
dbtypes "github.com/initia-labs/opinit-bots/db/types"
813
executortypes "github.com/initia-labs/opinit-bots/executor/types"
14+
merkletypes "github.com/initia-labs/opinit-bots/merkle/types"
915
"github.com/initia-labs/opinit-bots/node"
16+
"github.com/initia-labs/opinit-bots/node/rpcclient"
1017
"github.com/initia-labs/opinit-bots/types"
1118
"github.com/pkg/errors"
1219
)
@@ -72,3 +79,161 @@ func Migration015(db types.DB) error {
7279
return false, nil
7380
})
7481
}
82+
83+
func Migration0191(db types.DB) error {
84+
nodeDB := db.WithPrefix([]byte(types.ChildName))
85+
merkleDB := nodeDB.WithPrefix([]byte(types.MerkleName))
86+
87+
err := merkleDB.PrefixedIterate(merkletypes.FinalizedTreeKey, nil, func(key, value []byte) (bool, error) {
88+
var tree merkletypes.FinalizedTreeInfo
89+
err := json.Unmarshal(value, &tree)
90+
if err != nil {
91+
return true, err
92+
}
93+
94+
err = merkleDB.Delete(key)
95+
if err != nil {
96+
return true, err
97+
}
98+
fmt.Printf("delete finalized tree index: %d, start leaf index: %d, leaf count: %d\n", tree.TreeIndex, tree.StartLeafIndex, tree.LeafCount)
99+
return false, nil
100+
})
101+
if err != nil {
102+
return err
103+
}
104+
105+
nextSequence := uint64(1)
106+
changeWorkingTree := false
107+
err = merkleDB.PrefixedIterate(merkletypes.WorkingTreeKey, nil, func(key, value []byte) (bool, error) {
108+
if len(key) != len(merkletypes.WorkingTreeKey)+1+8 {
109+
return true, fmt.Errorf("unexpected working tree key; expected: %d; got: %d", len(merkletypes.WorkingTreeKey)+1+8, len(key))
110+
}
111+
112+
version := dbtypes.ToUint64Key(key[len(key)-8:])
113+
114+
var workingTree merkletypes.TreeInfo
115+
err := json.Unmarshal(value, &workingTree)
116+
if err != nil {
117+
return true, err
118+
}
119+
120+
if nextSequence != workingTree.StartLeafIndex {
121+
changeWorkingTree = true
122+
}
123+
124+
if changeWorkingTree {
125+
workingTree.StartLeafIndex = nextSequence
126+
workingTreeBz, err := json.Marshal(workingTree)
127+
if err != nil {
128+
return true, err
129+
}
130+
err = merkleDB.Set(key, workingTreeBz)
131+
if err != nil {
132+
return true, err
133+
}
134+
}
135+
136+
if workingTree.Done && workingTree.LeafCount != 0 {
137+
data, err := json.Marshal(executortypes.TreeExtraData{
138+
BlockNumber: types.MustUint64ToInt64(version),
139+
})
140+
if err != nil {
141+
return true, err
142+
}
143+
144+
treeHeight := types.MustIntToUint8(bits.Len64(workingTree.LeafCount - 1))
145+
if workingTree.LeafCount <= 1 {
146+
treeHeight = uint8(workingTree.LeafCount) //nolint
147+
}
148+
149+
treeRootHash := workingTree.LastSiblings[treeHeight]
150+
finalizedTreeInfo := merkletypes.FinalizedTreeInfo{
151+
TreeIndex: workingTree.Index,
152+
TreeHeight: treeHeight,
153+
Root: treeRootHash,
154+
StartLeafIndex: workingTree.StartLeafIndex,
155+
LeafCount: workingTree.LeafCount,
156+
ExtraData: data,
157+
}
158+
159+
finalizedTreeBz, err := json.Marshal(finalizedTreeInfo)
160+
if err != nil {
161+
return true, err
162+
}
163+
164+
err = merkleDB.Set(finalizedTreeInfo.Key(), finalizedTreeBz)
165+
if err != nil {
166+
return true, err
167+
}
168+
169+
fmt.Printf("finalized tree index: %d, start leaf index: %d, leaf count: %d, block height: %d\n", finalizedTreeInfo.TreeIndex, finalizedTreeInfo.StartLeafIndex, finalizedTreeInfo.LeafCount, version)
170+
nextSequence = workingTree.StartLeafIndex + workingTree.LeafCount
171+
}
172+
return false, nil
173+
})
174+
if err != nil {
175+
return err
176+
}
177+
return nil
178+
}
179+
180+
func Migration0192(ctx context.Context, db types.DB, rpcClient *rpcclient.RPCClient) error {
181+
nodeDB := db.WithPrefix([]byte(types.ChildName))
182+
merkleDB := nodeDB.WithPrefix([]byte(types.MerkleName))
183+
184+
timer := time.NewTicker(types.PollingInterval(ctx))
185+
defer timer.Stop()
186+
187+
return merkleDB.PrefixedIterate(merkletypes.FinalizedTreeKey, nil, func(key, value []byte) (bool, error) {
188+
var tree merkletypes.FinalizedTreeInfo
189+
err := json.Unmarshal(value, &tree)
190+
if err != nil {
191+
return true, err
192+
}
193+
194+
var extraData executortypes.TreeExtraData
195+
err = json.Unmarshal(tree.ExtraData, &extraData)
196+
if err != nil {
197+
return true, err
198+
}
199+
200+
if extraData.BlockHash != nil {
201+
return false, nil
202+
}
203+
204+
for {
205+
select {
206+
case <-ctx.Done():
207+
return true, ctx.Err()
208+
case <-timer.C:
209+
}
210+
height := extraData.BlockNumber + 1
211+
header, err := rpcClient.Header(ctx, &height)
212+
if err != nil {
213+
fmt.Printf("failed to get header for block height: %d; %s\n", height, err.Error())
214+
continue
215+
}
216+
217+
extraData.BlockHash = header.Header.LastBlockID.Hash
218+
break
219+
}
220+
221+
tree.ExtraData, err = json.Marshal(extraData)
222+
if err != nil {
223+
return true, err
224+
}
225+
treeBz, err := json.Marshal(tree)
226+
if err != nil {
227+
return true, err
228+
}
229+
err = merkleDB.Set(key, treeBz)
230+
if err != nil {
231+
return true, err
232+
}
233+
outputRoot := ophosttypes.GenerateOutputRoot(1, tree.Root, extraData.BlockHash)
234+
outputRootStr := base64.StdEncoding.EncodeToString(outputRoot[:])
235+
236+
fmt.Printf("finalized tree index: %d, start leaf index: %d, leaf count: %d, block height: %d, block hash: %X, outputRoot: %s\n", tree.TreeIndex, tree.StartLeafIndex, tree.LeafCount, extraData.BlockNumber, extraData.BlockHash, outputRootStr)
237+
return false, nil
238+
})
239+
}

provider/child/child.go

Lines changed: 21 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -119,14 +119,28 @@ func (b *BaseChild) Initialize(
119119
var l2Sequence uint64
120120
if b.node.HeightInitialized() {
121121
if !disableDeleteFutureWithdrawals {
122-
l2Sequence, err = b.QueryNextL2Sequence(ctx, processedHeight)
123-
if err != nil {
124-
return 0, err
125-
}
122+
l2Sequence = 1
123+
if processedHeight != 0 {
124+
l2Sequence, err = b.QueryNextL2Sequence(ctx, processedHeight)
125+
if err != nil {
126+
return 0, err
127+
}
126128

127-
err = b.mk.DeleteFutureFinalizedTrees(l2Sequence)
128-
if err != nil {
129-
return 0, err
129+
err = b.mk.DeleteFutureFinalizedTrees(l2Sequence)
130+
if err != nil {
131+
return 0, err
132+
}
133+
}
134+
b.initializeTreeFn = func(blockHeight int64) (bool, error) {
135+
if processedHeight+1 == blockHeight {
136+
b.logger.Info("initialize tree", zap.Uint64("index", startOutputIndex))
137+
err := b.mk.InitializeWorkingTree(startOutputIndex, l2Sequence)
138+
if err != nil {
139+
return false, err
140+
}
141+
return true, nil
142+
}
143+
return false, nil
130144
}
131145
}
132146

@@ -135,18 +149,6 @@ func (b *BaseChild) Initialize(
135149
if err != nil {
136150
return 0, err
137151
}
138-
139-
b.initializeTreeFn = func(blockHeight int64) (bool, error) {
140-
if processedHeight+1 == blockHeight {
141-
b.logger.Info("initialize tree", zap.Uint64("index", startOutputIndex))
142-
err := b.mk.InitializeWorkingTree(startOutputIndex, 1)
143-
if err != nil {
144-
return false, err
145-
}
146-
return true, nil
147-
}
148-
return false, nil
149-
}
150152
}
151153

152154
if b.OracleEnabled() && oracleKeyringConfig != nil {

0 commit comments

Comments
 (0)