func makeDefaultSendTx(t *testing.T, typ string, addr []byte, amt int64) *types.SendTx { nonce := getNonce(t, typ, user[0].Address) tx := types.NewSendTx() tx.AddInputWithNonce(user[0].PubKey, amt, nonce+1) tx.AddOutput(addr, amt) return tx }
func newSendTx(t *testing.T, mempool *Mempool, from *acm.PrivAccount, to []byte, amt int64) types.Tx { tx := types.NewSendTx() tx.AddInput(mempool.GetCache(), from.PubKey, amt) tx.AddOutput(to, amt) tx.SignInput(config.GetString("chain_id"), 0, from) if err := mempool.AddTx(tx); err != nil { t.Fatal(err) } return tx }
func TestTxSequence(t *testing.T) { state, privAccounts, _ := RandGenesisState(3, true, 1000, 1, true, 1000) acc0 := state.GetAccount(privAccounts[0].PubKey.Address()) acc0PubKey := privAccounts[0].PubKey acc1 := state.GetAccount(privAccounts[1].PubKey.Address()) // Test a variety of sequence numbers for the tx. // The tx should only pass when i == 1. for i := -1; i < 3; i++ { sequence := acc0.Sequence + i tx := types.NewSendTx() tx.AddInputWithNonce(acc0PubKey, 1, sequence) tx.AddOutput(acc1.Address, 1) tx.Inputs[0].Signature = privAccounts[0].Sign(state.ChainID, tx) stateCopy := state.Copy() err := execTxWithState(stateCopy, tx, true) if i == 1 { // Sequence is good. if err != nil { t.Errorf("Expected good sequence to pass: %v", err) } // Check acc.Sequence. newAcc0 := stateCopy.GetAccount(acc0.Address) if newAcc0.Sequence != sequence { t.Errorf("Expected account sequence to change to %v, got %v", sequence, newAcc0.Sequence) } } else { // Sequence is bad. if err == nil { t.Errorf("Expected bad sequence to fail") } // Check acc.Sequence. (shouldn't have changed) newAcc0 := stateCopy.GetAccount(acc0.Address) if newAcc0.Sequence != acc0.Sequence { t.Errorf("Expected account sequence to not change from %v, got %v", acc0.Sequence, newAcc0.Sequence) } } } }
// Make a random send transaction from srcIndex to N other accounts. // balance: balance to send from input // sequence: sequence to sign with // inputPriv: input privAccount func makeRandomTransaction(balance int64, sequence int, inputPriv *acm.PrivAccount, sendCount int, accounts []*acm.Account) *types.SendTx { if sendCount >= len(accounts) { PanicSanity("Cannot make tx with sendCount >= len(accounts)") } // Remember which accounts were chosen accMap := map[string]struct{}{} accMap[string(inputPriv.Address)] = struct{}{} // Find a selection of accounts to send to outputs := []*acm.Account{} for i := 0; i < sendCount; i++ { for { idx := RandInt() % len(accounts) account := accounts[idx] if _, ok := accMap[string(account.Address)]; ok { continue } accMap[string(account.Address)] = struct{}{} outputs = append(outputs, account) break } } // Construct SendTx sendTx := types.NewSendTx() err := sendTx.AddInputWithNonce(inputPriv.PubKey, balance, sequence) if err != nil { panic(err) } for _, output := range outputs { sendTx.AddOutput(output.Address, balance/int64(len(outputs))) } // Sign SendTx sendTx.SignInput("tendermint_testnet_9", 0, inputPriv) return sendTx }
func send_tx() { // Get PrivAccount var privAccount *acm.PrivAccount secret := getString("Enter your secret, or just hit <Enter> to enter a private key in HEX.\n> ") if secret == "" { privKeyBytes := getByteSliceFromHex("Enter your private key in HEX (e.g. E353CAD81134A301A542AEBE2D2E4EF1A64A145117EC72743AE9C9D171A4AA69F3A7DD670A9E9307AAED000D97D5B3C07D90276BFCEEDA5ED11DA089A4E87A81):\n> ") privAccount = acm.GenPrivAccountFromPrivKeyBytes(privKeyBytes) } else { // Auto-detect private key hex if len(secret) == 128 { privKeyBytes, err := hex.DecodeString(secret) if err == nil { fmt.Println("Detected priv-key bytes...") privAccount = acm.GenPrivAccountFromPrivKeyBytes(privKeyBytes) } else { fmt.Println("That's a long seed...") privAccount = acm.GenPrivAccountFromSecret(secret) } } else { privAccount = acm.GenPrivAccountFromSecret(secret) } } pubKey := privAccount.PubKey // Get account data cli := cclient.NewClient("http://localhost:46657", "JSONRPC") res, err := cli.GetAccount(privAccount.Address) if err != nil { Exit(Fmt("Error fetching account: %v", err)) } if res == nil { Exit(Fmt("No account was found with that secret/private-key")) } inputAcc := res.Account fmt.Printf(` Source account: Address: %X PubKey: %v Sequence: %v Balance: %v Permissions: %v `, inputAcc.Address, pubKey, inputAcc.Sequence, inputAcc.Balance, inputAcc.Permissions) output := getByteSliceFromHex("\nEnter the output address in HEX:\n> ") amount := getInt64("Enter the amount to send:\n> ") // Construct transaction tx := types.NewSendTx() tx.AddInputWithNonce(pubKey, amount, inputAcc.Sequence+1) tx.AddOutput(output, amount) tx.Inputs[0].Signature = privAccount.Sign(config.GetString("chain_id"), tx) fmt.Println("Signed SendTx!: ", tx) // Sign up for events wsCli := cclient.NewWSClient("ws://localhost:46657/websocket") wsCli.Start() err = wsCli.Subscribe(types.EventStringAccInput(inputAcc.Address)) if err != nil { Exit(Fmt("Error subscribing to account send event: %v", err)) } // Broadcast transaction _, err = cli.BroadcastTx(tx) if err != nil { Exit(Fmt("Error broadcasting transaction: %v", err)) } fmt.Println("Waiting for confirmation...") _ = <-wsCli.EventsCh fmt.Println("Confirmed.") }