func cliRestore(cmd *cobra.Command, args []string) { if len(args) != 1 { Exit(fmt.Errorf("Enter the chain id")) } chainID := args[0] var err error var b []byte if IPFShash == "" { fi, _ := os.Stdin.Stat() if fi.Size() == 0 { Exit(fmt.Errorf("Please pass data to restore on Stdin or specify IPFS hash with --ipfs=\"[hash]\"")) } b, err = ioutil.ReadAll(os.Stdin) IfExit(err) } else { url := composeIPFSUrl(HostFlag, ApiFlag) w := bytes.NewBuffer([]byte{}) w.Write([]byte("Reading file from IPFS. Hash =>\t" + IPFShash + "\n")) b, err = IPFSCat(url, IPFShash, ApiFlag, w) IfExit(err) } CoreRestore(chainID, b) stateDB := dbm.GetDB("state") newState := sm.LoadState(stateDB) fmt.Printf("State hash: %X\n", newState.Hash()) }
func TestRestoreDump(t *testing.T) { b1, err := ioutil.ReadFile(path.Join(TestDir, "data1.json")) // with validators if err != nil { t.Fatal(err) } b2, err := ioutil.ReadFile(path.Join(TestDir, "data2.json")) // without if err != nil { t.Fatal(err) } b1 = bytes.Trim(b1, "\n") b2 = bytes.Trim(b2, "\n") // restore to a memdir config.Set("db_backend", "memdb") cfg.ApplyConfig(config) // Notify modules of new config CoreRestore("", b1) stateDB := dbm.GetDB("state") st := sm.LoadState(stateDB) acc := st.GetAccount(ptypes.GlobalPermissionsAddress) fmt.Println(acc) dump1 := CoreDump(true) // with validators if bytes.Compare(b1, dump1) != 0 { ld, lb := len(dump1), len(b1) max := int(math.Max(float64(ld), float64(lb))) n := 100 for i := 0; i < max/n; i++ { dd := dump1[i*n : (i+1)*n] bb := b1[i*n : (i+1)*n] if bytes.Compare(dd, bb) != 0 { t.Fatalf("Error in dumps! Got \n\n\n\n %s \n\n\n\n Expected \n\n\n\n %s", dd, bb) } } } CoreRestore("", b2) dump2 := CoreDump(false) //without validators if bytes.Compare(b2, dump2) != 0 { ld, lb := len(dump2), len(b2) max := int(math.Max(float64(ld), float64(lb))) n := 100 for i := 0; i < max/n; i++ { dd := dump2[i*n : (i+1)*n] bb := b2[i*n : (i+1)*n] if bytes.Compare(dd, bb) != 0 { t.Fatalf("Error in dumps! Got \n\n\n\n %s \n\n\n\n Expected \n\n\n\n %s", dd, bb) } } } }
// dump the latest state to json func CoreDump(dumpval bool) []byte { // Get State stateDB := dbm.GetDB("state") st := sm.LoadState(stateDB) if st == nil { Exit(fmt.Errorf("Error: state loaded from %s is nil!", config.GetString("db_dir"))) } stJ := new(State) //default is true, flag omits vals from dump if dumpval { stJ.BondedValidators = st.BondedValidators stJ.LastBondedValidators = st.LastBondedValidators stJ.UnbondingValidators = st.UnbondingValidators } // iterate through accounts tree // track storage roots as we go storageRoots := [][]byte{} st.GetAccounts().Iterate(func(key interface{}, value interface{}) (stopped bool) { acc := value.(*acm.Account) stJ.Accounts = append(stJ.Accounts, acc) storageRoots = append(storageRoots, acc.StorageRoot) return false }) // grab all storage for i, root := range storageRoots { if len(root) == 0 { continue } accStorage := &AccountStorage{Address: stJ.Accounts[i].Address} storage := merkle.NewIAVLTree(wire.BasicCodec, wire.BasicCodec, 1024, stateDB) storage.Load(root) storage.Iterate(func(key interface{}, value interface{}) (stopped bool) { k, v := key.([]byte), value.([]byte) accStorage.Storage = append(accStorage.Storage, &Storage{k, v}) return false }) stJ.AccountsStorage = append(stJ.AccountsStorage, accStorage) } // get all validator infos if dumpval { st.GetValidatorInfos().Iterate(func(key interface{}, value interface{}) (stopped bool) { vi := value.(*types.ValidatorInfo) stJ.ValidatorInfos = append(stJ.ValidatorInfos, vi) return false }) } // get all name entries st.GetNames().Iterate(func(key interface{}, value interface{}) (stopped bool) { name := value.(*types.NameRegEntry) stJ.NameReg = append(stJ.NameReg, name) return false }) w, n, err := new(bytes.Buffer), new(int64), new(error) wire.WriteJSON(stJ, w, n, err) IfExit(*err) w2 := new(bytes.Buffer) json.Indent(w2, w.Bytes(), "", "\t") return w2.Bytes() }