package rpctest import ( "bytes" "fmt" "github.com/tendermint/tendermint/account" . "github.com/tendermint/tendermint/common" "github.com/tendermint/tendermint/types" "testing" ) var doNothing = func(eid string, b []byte) error { return nil } func testStatus(t *testing.T, typ string) { client := clients[typ] resp, err := client.Status() if err != nil { t.Fatal(err) } if resp.ChainID != chainID { t.Fatal(fmt.Errorf("ChainID mismatch: got %s expected %s", resp.ChainID, chainID)) } } func testGenPriv(t *testing.T, typ string) { client := clients[typ] privAcc, err := client.GenPrivAccount() if err != nil { t.Fatal(err) } if len(privAcc.Address) == 0 { t.Fatal("Failed to generate an address") } } func testGetAccount(t *testing.T, typ string) { acc := getAccount(t, typ, user[0].Address) if acc == nil { t.Fatalf("Account was nil") } if bytes.Compare(acc.Address, user[0].Address) != 0 { t.Fatalf("Failed to get correct account. Got %x, expected %x", acc.Address, user[0].Address) } } func testSignedTx(t *testing.T, typ string) { amt := uint64(100) toAddr := user[1].Address testOneSignTx(t, typ, toAddr, amt) toAddr = user[2].Address testOneSignTx(t, typ, toAddr, amt) toAddr = user[3].Address testOneSignTx(t, typ, toAddr, amt) } func testOneSignTx(t *testing.T, typ string, addr []byte, amt uint64) { tx := makeDefaultSendTx(t, typ, addr, amt) tx2 := signTx(t, typ, tx, user[0]) tx2hash := account.HashSignBytes(chainID, tx2) tx.SignInput(chainID, 0, user[0]) txhash := account.HashSignBytes(chainID, tx) if bytes.Compare(txhash, tx2hash) != 0 { t.Fatal("Got different signatures for signing via rpc vs tx_utils") } tx_ := signTx(t, typ, tx, user[0]) tx = tx_.(*types.SendTx) checkTx(t, user[0].Address, user[0], tx) } func testBroadcastTx(t *testing.T, typ string) { amt := uint64(100) toAddr := user[1].Address tx := makeDefaultSendTxSigned(t, typ, toAddr, amt) receipt := broadcastTx(t, typ, tx) if receipt.CreatesContract > 0 { t.Fatal("This tx does not create a contract") } if len(receipt.TxHash) == 0 { t.Fatal("Failed to compute tx hash") } pool := node.MempoolReactor().Mempool txs := pool.GetProposalTxs() if len(txs) != mempoolCount { t.Fatalf("The mem pool has %d txs. Expected %d", len(txs), mempoolCount) } tx2 := txs[mempoolCount-1].(*types.SendTx) n, err := new(int64), new(error) buf1, buf2 := new(bytes.Buffer), new(bytes.Buffer) tx.WriteSignBytes(chainID, buf1, n, err) tx2.WriteSignBytes(chainID, buf2, n, err) if bytes.Compare(buf1.Bytes(), buf2.Bytes()) != 0 { t.Fatal("inconsistent hashes for mempool tx and sent tx") } } func testGetStorage(t *testing.T, typ string) { con := newWSCon(t) eid := types.EventStringNewBlock() subscribe(t, con, eid) defer func() { unsubscribe(t, con, eid) con.Close() }() amt, gasLim, fee := uint64(1100), uint64(1000), uint64(1000) code := []byte{0x60, 0x5, 0x60, 0x1, 0x55} tx := makeDefaultCallTx(t, typ, nil, code, amt, gasLim, fee) receipt := broadcastTx(t, typ, tx) if receipt.CreatesContract == 0 { t.Fatal("This tx creates a contract") } if len(receipt.TxHash) == 0 { t.Fatal("Failed to compute tx hash") } contractAddr := receipt.ContractAddr if len(contractAddr) == 0 { t.Fatal("Creates contract but resulting address is empty") } // allow it to get mined waitForEvent(t, con, eid, true, func() {}, doNothing) mempoolCount = 0 v := getStorage(t, typ, contractAddr, []byte{0x1}) got := LeftPadWord256(v) expected := LeftPadWord256([]byte{0x5}) if got.Compare(expected) != 0 { t.Fatalf("Wrong storage value. Got %x, expected %x", got.Bytes(), expected.Bytes()) } } func testCallCode(t *testing.T, typ string) { client := clients[typ] // add two integers and return the result code := []byte{0x60, 0x5, 0x60, 0x6, 0x1, 0x60, 0x0, 0x52, 0x60, 0x20, 0x60, 0x0, 0xf3} data := []byte{} expected := []byte{0xb} callCode(t, client, code, data, expected) // pass two ints as calldata, add, and return the result code = []byte{0x60, 0x0, 0x35, 0x60, 0x20, 0x35, 0x1, 0x60, 0x0, 0x52, 0x60, 0x20, 0x60, 0x0, 0xf3} data = append(LeftPadWord256([]byte{0x5}).Bytes(), LeftPadWord256([]byte{0x6}).Bytes()...) expected = []byte{0xb} callCode(t, client, code, data, expected) } func testCall(t *testing.T, typ string) { con := newWSCon(t) eid := types.EventStringNewBlock() subscribe(t, con, eid) defer func() { unsubscribe(t, con, eid) con.Close() }() client := clients[typ] // create the contract amt, gasLim, fee := uint64(6969), uint64(1000), uint64(1000) code, _, _ := simpleContract() tx := makeDefaultCallTx(t, typ, nil, code, amt, gasLim, fee) receipt := broadcastTx(t, typ, tx) if receipt.CreatesContract == 0 { t.Fatal("This tx creates a contract") } if len(receipt.TxHash) == 0 { t.Fatal("Failed to compute tx hash") } contractAddr := receipt.ContractAddr if len(contractAddr) == 0 { t.Fatal("Creates contract but resulting address is empty") } // allow it to get mined waitForEvent(t, con, eid, true, func() {}, doNothing) mempoolCount = 0 // run a call through the contract data := []byte{} expected := []byte{0xb} callContract(t, client, contractAddr, data, expected) } func testNameReg(t *testing.T, typ string) { client := clients[typ] con := newWSCon(t) eid := types.EventStringNewBlock() subscribe(t, con, eid) defer func() { unsubscribe(t, con, eid) con.Close() }() types.MinNameRegistrationPeriod = 1 // register a new name, check if its there // since entries ought to be unique and these run against different clients, we append the typ name := "ye_old_domain_name_" + typ data := "if not now, when" fee := uint64(1000) numDesiredBlocks := uint64(2) amt := fee + numDesiredBlocks*types.NameCostPerByte*types.NameCostPerBlock*types.BaseEntryCost(name, data) tx := makeDefaultNameTx(t, typ, name, data, amt, fee) broadcastTx(t, typ, tx) // commit block waitForEvent(t, con, eid, true, func() {}, doNothing) mempoolCount = 0 entry := getNameRegEntry(t, typ, name) if entry.Data != data { t.Fatal(fmt.Sprintf("Err on entry.Data: Got %s, expected %s", entry.Data, data)) } if bytes.Compare(entry.Owner, user[0].Address) != 0 { t.Fatal(fmt.Sprintf("Err on entry.Owner: Got %s, expected %s", entry.Owner, user[0].Address)) } // update the data as the owner, make sure still there numDesiredBlocks = uint64(2) data = "these are amongst the things I wish to bestow upon the youth of generations come: a safe supply of honey, and a better money. For what else shall they need" amt = fee + numDesiredBlocks*types.NameCostPerByte*types.NameCostPerBlock*types.BaseEntryCost(name, data) tx = makeDefaultNameTx(t, typ, name, data, amt, fee) broadcastTx(t, typ, tx) // commit block waitForEvent(t, con, eid, true, func() {}, doNothing) mempoolCount = 0 entry = getNameRegEntry(t, typ, name) if entry.Data != data { t.Fatal(fmt.Sprintf("Err on entry.Data: Got %s, expected %s", entry.Data, data)) } // try to update as non owner, should fail nonce := getNonce(t, typ, user[1].Address) data2 := "this is not my beautiful house" tx = types.NewNameTxWithNonce(user[1].PubKey, name, data2, amt, fee, nonce+1) tx.Sign(chainID, user[1]) _, err := client.BroadcastTx(tx) if err == nil { t.Fatal("Expected error on NameTx") } // commit block waitForEvent(t, con, eid, true, func() {}, doNothing) // now the entry should be expired, so we can update as non owner _, err = client.BroadcastTx(tx) waitForEvent(t, con, eid, true, func() {}, doNothing) mempoolCount = 0 entry = getNameRegEntry(t, typ, name) if entry.Data != data2 { t.Fatal(fmt.Sprintf("Error on entry.Data: Got %s, expected %s", entry.Data, data2)) } if bytes.Compare(entry.Owner, user[1].Address) != 0 { t.Fatal(fmt.Sprintf("Err on entry.Owner: Got %s, expected %s", entry.Owner, user[1].Address)) } }