diff --git a/cmd/walletd/node.go b/cmd/walletd/node.go index d40c8a4..008c835 100644 --- a/cmd/walletd/node.go +++ b/cmd/walletd/node.go @@ -167,6 +167,7 @@ func newNode(addr, dir string, chainNetwork string, useUPNP bool) (*node, error) case "anagami": network, genesisBlock = TestnetAnagami() bootstrapPeers = anagamiBootstrap + testnetFixDBTree(dir) default: return nil, errors.New("invalid network: must be one of 'mainnet', 'zen', or 'anagami'") } diff --git a/cmd/walletd/testnet.go b/cmd/walletd/testnet.go index 8d477cd..82a6892 100644 --- a/cmd/walletd/testnet.go +++ b/cmd/walletd/testnet.go @@ -6,9 +6,12 @@ import ( "log" "math/big" "os" + "path/filepath" "reflect" "time" + bolt "go.etcd.io/bbolt" + "go.sia.tech/core/chain" "go.sia.tech/core/consensus" "go.sia.tech/core/types" "go.sia.tech/walletd/api" @@ -380,3 +383,58 @@ func printTestnetTxpool(c *api.Client, seed wallet.Seed) { } } } + +func testnetFixDBTree(dir string) { + if _, err := os.Stat(filepath.Join(dir, "consensus.db")); err != nil { + log.Fatal(err) + } + bdb, err := bolt.Open(filepath.Join(dir, "consensus.db"), 0600, nil) + if err != nil { + log.Fatal(err) + } + db := &boltDB{db: bdb} + defer db.Close() + if db.Bucket([]byte("tree-fix")) != nil { + return + } + + fmt.Print("Fixing consensus.db Merkle tree...") + + network, genesisBlock := TestnetAnagami() + dbstore, tipState, err := chain.NewDBStore(db, network, genesisBlock) + if err != nil { + log.Fatal(err) + } + cm := chain.NewManager(dbstore, tipState) + + bdb2, err := bolt.Open(filepath.Join(dir, "consensus.db-fixed"), 0600, nil) + if err != nil { + log.Fatal(err) + } + db2 := &boltDB{db: bdb2} + defer db2.Close() + dbstore2, tipState2, err := chain.NewDBStore(db2, network, genesisBlock) + if err != nil { + log.Fatal(err) + } + cm2 := chain.NewManager(dbstore2, tipState2) + + for cm2.Tip() != cm.Tip() { + index, _ := cm.BestIndex(cm2.Tip().Height + 1) + b, _ := cm.Block(index.ID) + if err := cm2.AddBlocks([]types.Block{b}); err != nil { + log.Fatal(err) + } + } + + if _, err := db2.CreateBucket([]byte("tree-fix")); err != nil { + log.Fatal(err) + } else if err := db.Close(); err != nil { + log.Fatal(err) + } else if err := db2.Close(); err != nil { + log.Fatal(err) + } else if err := os.Rename(filepath.Join(dir, "consensus.db-fixed"), filepath.Join(dir, "consensus.db")); err != nil { + log.Fatal(err) + } + fmt.Println("done.") +} diff --git a/internal/walletutil/manager.go b/internal/walletutil/manager.go index 77b8d1f..185006b 100644 --- a/internal/walletutil/manager.go +++ b/internal/walletutil/manager.go @@ -244,6 +244,9 @@ func (wm *JSONWalletManager) AddWallet(name string, info json.RawMessage) error // update existing wallet mw.info = info return wm.save() + } else if _, err := os.Stat(filepath.Join(wm.dir, "wallets", name+".json")); err == nil { + // shouldn't happen in normal conditions + return errors.New("a wallet with that name already exists, but is absent from wallets.json") } store, _, err := NewJSONStore(filepath.Join(wm.dir, "wallets", name+".json")) if err != nil {