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 := int64(1100), int64(1000), int64(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()) } }
// Save Block, save the +2/3 Commits we've seen func (cs *ConsensusState) saveBlock(block *types.Block, blockParts *types.PartSet, commits *types.VoteSet) { // The proposal must be valid. if err := cs.stageBlock(block, blockParts); err != nil { PanicSanity(Fmt("saveBlock() an invalid block: %v", err)) } // Save to blockStore. if cs.blockStore.Height() < block.Height { seenValidation := commits.MakeValidation() cs.blockStore.SaveBlock(block, blockParts, seenValidation) } // Save the state. cs.stagedState.Save() // Update mempool. cs.mempoolReactor.Mempool.ResetForBlockAndState(block, cs.stagedState) // Fire off event if cs.evsw != nil && cs.evc != nil { cs.evsw.FireEvent(types.EventStringNewBlock(), types.EventDataNewBlock{block}) go cs.evc.Flush() } }
// receive a new block message func TestWSNewBlock(t *testing.T) { con := newWSCon(t) eid := types.EventStringNewBlock() subscribe(t, con, eid) defer func() { unsubscribe(t, con, eid) con.Close() }() waitForEvent(t, con, eid, true, func() {}, func(eid string, b []byte) error { fmt.Println("Check:", string(b)) return nil }) }
// receive a few new block messages in a row, with increasing height func TestWSBlockchainGrowth(t *testing.T) { if testing.Short() { t.Skip("skipping test in short mode.") } con := newWSCon(t) eid := types.EventStringNewBlock() subscribe(t, con, eid) defer func() { unsubscribe(t, con, eid) con.Close() }() // listen for NewBlock, ensure height increases by 1 unmarshalValidateBlockchain(t, con, eid) }
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 := int64(6969), int64(1000), int64(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, user[0].PubKey.Address(), contractAddr, data, expected) }
func testNameReg(t *testing.T, typ string) { client := clients[typ] con := newWSCon(t) 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 := int64(1000) numDesiredBlocks := int64(2) amt := fee + numDesiredBlocks*types.NameByteCostMultiplier*types.NameBlockCostMultiplier*types.NameBaseCost(name, data) eid := types.EventStringNameReg(name) subscribe(t, con, eid) tx := makeDefaultNameTx(t, typ, name, data, amt, fee) broadcastTx(t, typ, tx) // verify the name by both using the event and by checking get_name waitForEvent(t, con, eid, true, func() {}, func(eid string, b []byte) error { // TODO: unmarshal the response tx, err := unmarshalResponseNameReg(b) if err != nil { return err } if tx.Name != name { t.Fatal(fmt.Sprintf("Err on received event tx.Name: Got %s, expected %s", tx.Name, name)) } if tx.Data != data { t.Fatal(fmt.Sprintf("Err on received event tx.Data: Got %s, expected %s", tx.Data, data)) } return nil }) 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)) } unsubscribe(t, con, eid) // for the rest we just use new block event // since we already tested the namereg event eid = types.EventStringNewBlock() subscribe(t, con, eid) defer func() { unsubscribe(t, con, eid) con.Close() }() // update the data as the owner, make sure still there numDesiredBlocks = int64(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.NameByteCostMultiplier*types.NameBlockCostMultiplier*types.NameBaseCost(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)) } }
func subscribeAndWait(tx types.Tx, chainID, nodeAddr string, inputAddr []byte) (chan Msg, error) { // subscribe to event and wait for tx to be committed wsAddr := strings.TrimPrefix(nodeAddr, "http://") wsAddr = "ws://" + wsAddr + "websocket" logger.Debugf("Websocket Address %s\n", wsAddr) wsClient := cclient.NewWSClient(wsAddr) wsClient.Start() eid := types.EventStringAccInput(inputAddr) if err := wsClient.Subscribe(eid); err != nil { return nil, fmt.Errorf("Error subscribing to AccInput event: %v", err) } if err := wsClient.Subscribe(types.EventStringNewBlock()); err != nil { return nil, fmt.Errorf("Error subscribing to NewBlock event: %v", err) } resultChan := make(chan Msg, 1) var latestBlockHash []byte // Read message go func() { for { result := <-wsClient.EventsCh // if its a block, remember the block hash blockData, ok := result.Data.(types.EventDataNewBlock) if ok { logger.Infoln(blockData.Block) latestBlockHash = blockData.Block.Hash() continue } // we don't accept events unless they came after a new block (ie. in) if latestBlockHash == nil { continue } if result.Event != eid { logger.Debugf("received unsolicited event! Got %s, expected %s\n", result.Event, eid) continue } data, ok := result.Data.(types.EventDataTx) if !ok { resultChan <- Msg{Error: fmt.Errorf("response error: expected result.Data to be *types.EventDataTx")} return } if !bytes.Equal(types.TxID(chainID, data.Tx), types.TxID(chainID, tx)) { logger.Debugf("Received event for same input from another transaction: %X\n", types.TxID(chainID, data.Tx)) continue } if data.Exception != "" { resultChan <- Msg{BlockHash: latestBlockHash, Value: data.Return, Exception: data.Exception} return } // GOOD! resultChan <- Msg{BlockHash: latestBlockHash, Value: data.Return} return } }() // txs should take no more than 10 seconds timeoutTicker := time.Tick(time.Duration(MaxCommitWaitTimeSeconds) * time.Second) go func() { <-timeoutTicker resultChan <- Msg{Error: fmt.Errorf("timed out waiting for event")} return }() return resultChan, nil }