func TestEventId(t *testing.T) { var table = []struct { definition string expectations map[string]common.Hash }{ { definition: `[ { "type" : "event", "name" : "balance", "inputs": [{ "name" : "in", "type": "uint" }] }, { "type" : "event", "name" : "check", "inputs": [{ "name" : "t", "type": "address" }, { "name": "b", "type": "uint256" }] } ]`, expectations: map[string]common.Hash{ "balance": crypto.Keccak256Hash([]byte("balance(uint256)")), "check": crypto.Keccak256Hash([]byte("check(address,uint256)")), }, }, } for _, test := range table { abi, err := JSON(strings.NewReader(test.definition)) if err != nil { t.Fatal(err) } for name, event := range abi.Events { if event.Id() != test.expectations[name] { t.Errorf("expected id to be %x, got %x", test.expectations[name], event.Id()) } } } }
// mine generates a testnet struct literal with nodes at // various distances to the given target. func (n *preminedTestnet) mine(target NodeID) { n.target = target n.targetSha = crypto.Keccak256Hash(n.target[:]) found := 0 for found < bucketSize*10 { k := newkey() id := PubkeyID(&k.PublicKey) sha := crypto.Keccak256Hash(id[:]) ld := logdist(n.targetSha, sha) if len(n.dists[ld]) < bucketSize { n.dists[ld] = append(n.dists[ld], id) fmt.Println("found ID with ld", ld) found++ } } fmt.Println("&preminedTestnet{") fmt.Printf(" target: %#v,\n", n.target) fmt.Printf(" targetSha: %#v,\n", n.targetSha) fmt.Printf(" dists: [%d][]NodeID{\n", len(n.dists)) for ld, ns := range n.dists { if len(ns) == 0 { continue } fmt.Printf(" %d: []NodeID{\n", ld) for _, n := range ns { fmt.Printf(" MustHexID(\"%x\"),\n", n[:]) } fmt.Println(" },") } fmt.Println(" },") fmt.Println("}") }
// use testing instead of checker because checker does not support // printing/logging in tests (-check.vv does not work) func TestSnapshot2(t *testing.T) { db, _ := ethdb.NewMemDatabase() state, _ := New(common.Hash{}, db) stateobjaddr0 := toAddr([]byte("so0")) stateobjaddr1 := toAddr([]byte("so1")) var storageaddr common.Hash data0 := common.BytesToHash([]byte{17}) data1 := common.BytesToHash([]byte{18}) state.SetState(stateobjaddr0, storageaddr, data0) state.SetState(stateobjaddr1, storageaddr, data1) // db, trie are already non-empty values so0 := state.GetStateObject(stateobjaddr0) so0.SetBalance(big.NewInt(42)) so0.SetNonce(43) so0.SetCode(crypto.Keccak256Hash([]byte{'c', 'a', 'f', 'e'}), []byte{'c', 'a', 'f', 'e'}) so0.suicided = false so0.deleted = false state.setStateObject(so0) root, _ := state.Commit() state.Reset(root) // and one with deleted == true so1 := state.GetStateObject(stateobjaddr1) so1.SetBalance(big.NewInt(52)) so1.SetNonce(53) so1.SetCode(crypto.Keccak256Hash([]byte{'c', 'a', 'f', 'e', '2'}), []byte{'c', 'a', 'f', 'e', '2'}) so1.suicided = true so1.deleted = true state.setStateObject(so1) so1 = state.GetStateObject(stateobjaddr1) if so1 != nil { t.Fatalf("deleted object not nil when getting") } snapshot := state.Snapshot() state.RevertToSnapshot(snapshot) so0Restored := state.GetStateObject(stateobjaddr0) // Update lazily-loaded values before comparing. so0Restored.GetState(db, storageaddr) so0Restored.Code(db) // non-deleted is equal (restored) compareStateObjects(so0Restored, so0, t) // deleted should be nil, both before and after restore of state copy so1Restored := state.GetStateObject(stateobjaddr1) if so1Restored != nil { t.Fatalf("deleted object not nil after restoring snapshot: %+v", so1Restored) } }
// Execute executes the code using the input as call data during the execution. // It returns the EVM's return value, the new state and an error if it failed. // // Executes sets up a in memory, temporarily, environment for the execution of // the given code. It enabled the JIT by default and make sure that it's restored // to it's original state afterwards. func Execute(code, input []byte, cfg *Config) ([]byte, *state.StateDB, error) { if cfg == nil { cfg = new(Config) } setDefaults(cfg) if cfg.State == nil { db, _ := ethdb.NewMemDatabase() cfg.State, _ = state.New(common.Hash{}, db) } var ( vmenv = NewEnv(cfg, cfg.State) sender = cfg.State.CreateAccount(cfg.Origin) receiver = cfg.State.CreateAccount(common.StringToAddress("contract")) ) // set the receiver's (the executing contract) code for execution. receiver.SetCode(crypto.Keccak256Hash(code), code) // Call the code with the given configuration. ret, err := vmenv.Call( sender, receiver.Address(), input, cfg.GasLimit, cfg.GasPrice, cfg.Value, ) return ret, cfg.State, err }
func TestGetAuthContent(t *testing.T) { dir, err := ioutil.TempDir("", "httpclient-test") if err != nil { t.Fatal("cannot create temporary directory:", err) } defer os.RemoveAll(dir) client := New(dir) text := "test" hash := crypto.Keccak256Hash([]byte(text)) if err := ioutil.WriteFile(path.Join(dir, "test.content"), []byte(text), os.ModePerm); err != nil { t.Fatal("could not write test file", err) } content, err := client.GetAuthContent("file:///test.content", hash) if err != nil { t.Errorf("no error expected, got %v", err) } if string(content) != text { t.Errorf("incorrect content. expected %v, got %v", text, string(content)) } hash = common.Hash{} content, err = client.GetAuthContent("file:///test.content", hash) expected := "content hash mismatch 0000000000000000000000000000000000000000000000000000000000000000 != 9c22ff5f21f0b81b113e63f7db6da94fedef11b2119b4088b89664fb9a3cb658 (exp)" if err == nil { t.Errorf("expected error, got nothing") } else { if err.Error() != expected { t.Errorf("expected error '%s' got '%v'", expected, err) } } }
// makeTestState create a sample test state to test node-wise reconstruction. func makeTestState() (ethdb.Database, common.Hash, []*testAccount) { // Create an empty state db, _ := ethdb.NewMemDatabase() state, _ := New(common.Hash{}, db) // Fill it with some arbitrary data accounts := []*testAccount{} for i := byte(0); i < 96; i++ { obj := state.GetOrNewStateObject(common.BytesToAddress([]byte{i})) acc := &testAccount{address: common.BytesToAddress([]byte{i})} obj.AddBalance(big.NewInt(int64(11 * i))) acc.balance = big.NewInt(int64(11 * i)) obj.SetNonce(uint64(42 * i)) acc.nonce = uint64(42 * i) if i%3 == 0 { obj.SetCode(crypto.Keccak256Hash([]byte{i, i, i, i, i}), []byte{i, i, i, i, i}) acc.code = []byte{i, i, i, i, i} } state.updateStateObject(obj) accounts = append(accounts, acc) } root, _ := state.Commit() // Return the generated state return db, root, accounts }
func (req *findnode) handle(t *udp, from *net.UDPAddr, fromID NodeID, mac []byte) error { if expired(req.Expiration) { return errExpired } if t.db.node(fromID) == nil { // No bond exists, we don't process the packet. This prevents // an attack vector where the discovery protocol could be used // to amplify traffic in a DDOS attack. A malicious actor // would send a findnode request with the IP address and UDP // port of the target as the source address. The recipient of // the findnode packet would then send a neighbors packet // (which is a much bigger packet than findnode) to the victim. return errUnknownNode } target := crypto.Keccak256Hash(req.Target[:]) t.mutex.Lock() closest := t.closest(target, bucketSize).entries t.mutex.Unlock() p := neighbors{Expiration: uint64(time.Now().Add(expiration).Unix())} // Send neighbors in chunks with at most maxNeighbors per packet // to stay below the 1280 byte limit. for i, n := range closest { p.Nodes = append(p.Nodes, nodeToRPC(n)) if len(p.Nodes) == maxNeighbors || i == len(closest)-1 { t.send(from, neighborsPacket, p) p.Nodes = p.Nodes[:0] } } return nil }
// Hash returns the SHA3 hash of the envelope, calculating it if not yet done. func (self *Envelope) Hash() common.Hash { if (self.hash == common.Hash{}) { enc, _ := rlp.EncodeToBytes(self) self.hash = crypto.Keccak256Hash(enc) } return self.hash }
// Create creates a new contract with the given code func Create(env vm.Environment, caller vm.ContractRef, code []byte, gas, gasPrice, value *big.Int) (ret []byte, address common.Address, err error) { ret, address, err = exec(env, caller, nil, nil, crypto.Keccak256Hash(code), nil, code, gas, gasPrice, value) // Here we get an error if we run into maximum stack depth, // See: https://github.com/expanse-project/yellowpaper/pull/131 // and YP definitions for CREATE instruction if err != nil { return nil, address, err } return ret, address, err }
// NewProgram returns a new JIT program func NewProgram(code []byte) *Program { program := &Program{ Id: crypto.Keccak256Hash(code), mapping: make(map[uint64]uint64), destinations: make(map[uint64]struct{}), code: code, } programs.Add(program.Id, program) return program }
// NewNode creates a new node. It is mostly meant to be used for // testing purposes. func NewNode(id NodeID, ip net.IP, udpPort, tcpPort uint16) *Node { if ipv4 := ip.To4(); ipv4 != nil { ip = ipv4 } return &Node{ IP: ip, UDP: udpPort, TCP: tcpPort, ID: id, sha: crypto.Keccak256Hash(id[:]), } }
// node retrieves a node with a given id from the database. func (db *nodeDB) node(id NodeID) *Node { blob, err := db.lvl.Get(makeKey(id, nodeDBDiscoverRoot), nil) if err != nil { glog.V(logger.Detail).Infof("failed to retrieve node %v: %v", id, err) return nil } node := new(Node) if err := rlp.DecodeBytes(blob, node); err != nil { glog.V(logger.Warn).Infof("failed to decode node RLP: %v", err) return nil } node.sha = crypto.Keccak256Hash(node.ID[:]) return node }
func (s *StateSuite) TestDump(c *checker.C) { // generate a few entries obj1 := s.state.GetOrNewStateObject(toAddr([]byte{0x01})) obj1.AddBalance(big.NewInt(22)) obj2 := s.state.GetOrNewStateObject(toAddr([]byte{0x01, 0x02})) obj2.SetCode(crypto.Keccak256Hash([]byte{3, 3, 3, 3, 3, 3, 3}), []byte{3, 3, 3, 3, 3, 3, 3}) obj3 := s.state.GetOrNewStateObject(toAddr([]byte{0x02})) obj3.SetBalance(big.NewInt(44)) // write some of them to the trie s.state.updateStateObject(obj1) s.state.updateStateObject(obj2) s.state.Commit() // check that dump contains the state objects that are in trie got := string(s.state.Dump()) want := `{ "root": "71edff0130dd2385947095001c73d9e28d862fc286fca2b922ca6f6f3cddfdd2", "accounts": { "0000000000000000000000000000000000000001": { "balance": "22", "nonce": 0, "root": "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", "codeHash": "c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "code": "", "storage": {} }, "0000000000000000000000000000000000000002": { "balance": "44", "nonce": 0, "root": "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", "codeHash": "c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "code": "", "storage": {} }, "0000000000000000000000000000000000000102": { "balance": "0", "nonce": 0, "root": "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", "codeHash": "87874902497a5bb968da31a2998d8f22e949d1ef6214bcdedd8bae24cca4b9e3", "code": "03030303030303", "storage": {} } } }` if got != want { c.Errorf("dump mismatch:\ngot: %s\nwant: %s\n", got, want) } }
func (self *HTTPClient) GetAuthContent(uri string, hash common.Hash) ([]byte, error) { // retrieve content content, err := self.Get(uri, "") if err != nil { return nil, err } // check hash to authenticate content chash := crypto.Keccak256Hash(content) if chash != hash { return nil, fmt.Errorf("content hash mismatch %x != %x (exp)", hash[:], chash[:]) } return content, nil }
// DecodeRLP decodes an Envelope from an RLP data stream. func (self *Envelope) DecodeRLP(s *rlp.Stream) error { raw, err := s.Raw() if err != nil { return err } // The decoding of Envelope uses the struct fields but also needs // to compute the hash of the whole RLP-encoded envelope. This // type has the same structure as Envelope but is not an // rlp.Decoder so we can reuse the Envelope struct definition. type rlpenv Envelope if err := rlp.DecodeBytes(raw, (*rlpenv)(self)); err != nil { return err } self.hash = crypto.Keccak256Hash(raw) return nil }
// Resolve searches for a specific node with the given ID. // It returns nil if the node could not be found. func (tab *Table) Resolve(targetID NodeID) *Node { // If the node is present in the local table, no // network interaction is required. hash := crypto.Keccak256Hash(targetID[:]) tab.mutex.Lock() cl := tab.closest(hash, 1) tab.mutex.Unlock() if len(cl.entries) > 0 && cl.entries[0].ID == targetID { return cl.entries[0] } // Otherwise, do a network lookup. result := tab.Lookup(targetID) for _, n := range result { if n.ID == targetID { return n } } return nil }
// SetFallbackNodes sets the initial points of contact. These nodes // are used to connect to the network if the table is empty and there // are no known nodes in the database. func (tab *Table) SetFallbackNodes(nodes []*Node) error { for _, n := range nodes { if err := n.validateComplete(); err != nil { return fmt.Errorf("bad bootstrap/fallback node %q (%v)", n, err) } } tab.mutex.Lock() tab.nursery = make([]*Node, 0, len(nodes)) for _, n := range nodes { cpy := *n // Recompute cpy.sha because the node might not have been // created by NewNode or ParseNode. cpy.sha = crypto.Keccak256Hash(n.ID[:]) tab.nursery = append(tab.nursery, &cpy) } tab.mutex.Unlock() tab.refresh() return nil }
// InsertPreState populates the given database with the genesis // accounts defined by the test. func (t *BlockTest) InsertPreState(db ethdb.Database) (*state.StateDB, error) { statedb, err := state.New(common.Hash{}, db) if err != nil { return nil, err } for addrString, acct := range t.preAccounts { code, err := hex.DecodeString(strings.TrimPrefix(acct.Code, "0x")) if err != nil { return nil, err } balance, ok := new(big.Int).SetString(acct.Balance, 0) if !ok { return nil, err } nonce, err := strconv.ParseUint(prepInt(16, acct.Nonce), 16, 64) if err != nil { return nil, err } obj := statedb.CreateAccount(common.HexToAddress(addrString)) obj.SetCode(crypto.Keccak256Hash(code), code) obj.SetBalance(balance) obj.SetNonce(nonce) for k, v := range acct.Storage { statedb.SetState(common.HexToAddress(addrString), common.HexToHash(k), common.HexToHash(v)) } } root, err := statedb.Commit() if err != nil { return nil, fmt.Errorf("error writing state: %v", err) } if t.Genesis.Root() != root { return nil, fmt.Errorf("computed state root does not match genesis block: genesis=%x computed=%x", t.Genesis.Root().Bytes()[:4], root.Bytes()[:4]) } return statedb, nil }
func (self *StateDB) SetCode(addr common.Address, code []byte) { stateObject := self.GetOrNewStateObject(addr) if stateObject != nil { stateObject.SetCode(crypto.Keccak256Hash(code), code) } }
// end to end test func TestNatspecE2E(t *testing.T) { t.Skip() tf := testInit(t) defer tf.expanse.Stop() addr, _ := tf.expanse.Etherbase() // create a contractInfo file (mock cloud-deployed contract metadocs) // incidentally this is the info for the HashReg contract itself ioutil.WriteFile("/tmp/"+testFileName, []byte(testContractInfo), os.ModePerm) dochash := crypto.Keccak256Hash([]byte(testContractInfo)) // take the codehash for the contract we wanna test codeb := tf.xexp.CodeAtBytes(registrar.HashRegAddr) codehash := crypto.Keccak256Hash(codeb) reg := registrar.New(tf.xeth) _, err := reg.SetHashToHash(addr, codehash, dochash) if err != nil { t.Errorf("error registering: %v", err) } _, err = reg.SetUrlToHash(addr, dochash, "file:///"+testFileName) if err != nil { t.Errorf("error registering: %v", err) } if !processTxs(tf, t, 5) { return } // NatSpec info for register method of HashReg contract installed // now using the same transactions to check confirm messages tf.wantNatSpec = true // this is set so now the backend uses natspec confirmation _, err = reg.SetHashToHash(addr, codehash, dochash) if err != nil { t.Errorf("error calling contract registry: %v", err) } fmt.Printf("GlobalRegistrar: %v, HashReg: %v, UrlHint: %v\n", registrar.GlobalRegistrarAddr, registrar.HashRegAddr, registrar.UrlHintAddr) if tf.lastConfirm != testExpNotice { t.Errorf("Wrong confirm message. expected\n'%v', got\n'%v'", testExpNotice, tf.lastConfirm) } // test unknown method exp := fmt.Sprintf(testExpNotice2, registrar.HashRegAddr) _, err = reg.SetOwner(addr) if err != nil { t.Errorf("error setting owner: %v", err) } if tf.lastConfirm != exp { t.Errorf("Wrong confirm message, expected\n'%v', got\n'%v'", exp, tf.lastConfirm) } // test unknown contract exp = fmt.Sprintf(testExpNotice3, registrar.UrlHintAddr) _, err = reg.SetUrlToHash(addr, dochash, "file:///test.content") if err != nil { t.Errorf("error registering: %v", err) } if tf.lastConfirm != exp { t.Errorf("Wrong confirm message, expected '%v', got '%v'", exp, tf.lastConfirm) } }
OdrRequest hash common.Hash data []byte } // GetData returns the retrieved node data after a successful request func (req *NodeDataRequest) GetData() []byte { return req.data } // StoreResult stores the retrieved data in local database func (req *NodeDataRequest) StoreResult(db ethdb.Database) { db.Put(req.hash[:], req.GetData()) } var sha3_nil = crypto.Keccak256Hash(nil) // retrieveNodeData tries to retrieve node data with the given hash from the network func retrieveNodeData(ctx context.Context, odr OdrBackend, hash common.Hash) ([]byte, error) { if hash == sha3_nil { return nil, nil } res, _ := odr.Database().Get(hash[:]) if res != nil { return res, nil } r := &NodeDataRequest{hash: hash} if err := odr.Retrieve(ctx, r); err != nil { return nil, err } else { return r.GetData(), nil
import ( "bytes" "fmt" "github.com/expanse-project/go-expanse/common" "github.com/expanse-project/go-expanse/crypto" "github.com/expanse-project/go-expanse/logger" "github.com/expanse-project/go-expanse/logger/glog" ) var ( // This is the known root hash of an empty trie. emptyRoot = common.HexToHash("56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421") // This is the known hash of an empty state trie entry. emptyState = crypto.Keccak256Hash(nil) ) // Database must be implemented by backing stores for the trie. type Database interface { DatabaseWriter // Get returns the value for key from the database. Get(key []byte) (value []byte, err error) } // DatabaseWriter wraps the Put method of a backing store for the trie. type DatabaseWriter interface { // Put stores the mapping key->value in the database. // Implementations must not hold onto the value bytes, the trie // will reuse the slice across calls to Put. Put(key, value []byte) error
func testGetNodeData(t *testing.T, protocol int) { // Define three accounts to simulate transactions with acc1Key, _ := crypto.HexToECDSA("8a1f9a8f95be41cd7ccb6168179afb4504aefe388d1e14474d32c45c72ce7b7a") acc2Key, _ := crypto.HexToECDSA("49a7b37aa6f6645917e7b807e9d1c00d4fa71f18343b0d4122a4d2df64dd6fee") acc1Addr := crypto.PubkeyToAddress(acc1Key.PublicKey) acc2Addr := crypto.PubkeyToAddress(acc2Key.PublicKey) // Create a chain generator with some simple transactions (blatantly stolen from @fjl/chain_markets_test) generator := func(i int, block *core.BlockGen) { switch i { case 0: // In block 1, the test bank sends account #1 some ether. tx, _ := types.NewTransaction(block.TxNonce(testBank.Address), acc1Addr, big.NewInt(10000), params.TxGas, nil, nil).SignECDSA(testBankKey) block.AddTx(tx) case 1: // In block 2, the test bank sends some more ether to account #1. // acc1Addr passes it on to account #2. tx1, _ := types.NewTransaction(block.TxNonce(testBank.Address), acc1Addr, big.NewInt(1000), params.TxGas, nil, nil).SignECDSA(testBankKey) tx2, _ := types.NewTransaction(block.TxNonce(acc1Addr), acc2Addr, big.NewInt(1000), params.TxGas, nil, nil).SignECDSA(acc1Key) block.AddTx(tx1) block.AddTx(tx2) case 2: // Block 3 is empty but was mined by account #2. block.SetCoinbase(acc2Addr) block.SetExtra([]byte("yeehaw")) case 3: // Block 4 includes blocks 2 and 3 as uncle headers (with modified extra data). b2 := block.PrevBlock(1).Header() b2.Extra = []byte("foo") block.AddUncle(b2) b3 := block.PrevBlock(2).Header() b3.Extra = []byte("foo") block.AddUncle(b3) } } // Assemble the test environment pm := newTestProtocolManagerMust(t, false, 4, generator, nil) peer, _ := newTestPeer("peer", protocol, pm, true) defer peer.close() // Fetch for now the entire chain db hashes := []common.Hash{} for _, key := range pm.chaindb.(*ethdb.MemDatabase).Keys() { if len(key) == len(common.Hash{}) { hashes = append(hashes, common.BytesToHash(key)) } } p2p.Send(peer.app, 0x0d, hashes) msg, err := peer.app.ReadMsg() if err != nil { t.Fatalf("failed to read node data response: %v", err) } if msg.Code != 0x0e { t.Fatalf("response packet code mismatch: have %x, want %x", msg.Code, 0x0c) } var data [][]byte if err := msg.Decode(&data); err != nil { t.Fatalf("failed to decode response node data: %v", err) } // Verify that all hashes correspond to the requested data, and reconstruct a state tree for i, want := range hashes { if hash := crypto.Keccak256Hash(data[i]); hash != want { t.Errorf("data hash mismatch: have %x, want %x", hash, want) } } statedb, _ := ethdb.NewMemDatabase() for i := 0; i < len(data); i++ { statedb.Put(hashes[i].Bytes(), data[i]) } accounts := []common.Address{testBank.Address, acc1Addr, acc2Addr} for i := uint64(0); i <= pm.blockchain.CurrentBlock().NumberU64(); i++ { trie, _ := state.New(pm.blockchain.GetBlockByNumber(i).Root(), statedb) for j, acc := range accounts { state, _ := pm.blockchain.State() bw := state.GetBalance(acc) bh := trie.GetBalance(acc) if (bw != nil && bh == nil) || (bw == nil && bh != nil) { t.Errorf("test %d, account %d: balance mismatch: have %v, want %v", i, j, bh, bw) } if bw != nil && bh != nil && bw.Cmp(bw) != 0 { t.Errorf("test %d, account %d: balance mismatch: have %v, want %v", i, j, bh, bw) } } } }
func (tab *Table) lookup(targetID NodeID, refreshIfEmpty bool) []*Node { var ( target = crypto.Keccak256Hash(targetID[:]) asked = make(map[NodeID]bool) seen = make(map[NodeID]bool) reply = make(chan []*Node, alpha) pendingQueries = 0 result *nodesByDistance ) // don't query further if we hit ourself. // unlikely to happen often in practice. asked[tab.self.ID] = true for { tab.mutex.Lock() // generate initial result set result = tab.closest(target, bucketSize) tab.mutex.Unlock() if len(result.entries) > 0 || !refreshIfEmpty { break } // The result set is empty, all nodes were dropped, refresh. // We actually wait for the refresh to complete here. The very // first query will hit this case and run the bootstrapping // logic. <-tab.refresh() refreshIfEmpty = false } for { // ask the alpha closest nodes that we haven't asked yet for i := 0; i < len(result.entries) && pendingQueries < alpha; i++ { n := result.entries[i] if !asked[n.ID] { asked[n.ID] = true pendingQueries++ go func() { // Find potential neighbors to bond with r, err := tab.net.findnode(n.ID, n.addr(), targetID) if err != nil { // Bump the failure counter to detect and evacuate non-bonded entries fails := tab.db.findFails(n.ID) + 1 tab.db.updateFindFails(n.ID, fails) glog.V(logger.Detail).Infof("Bumping failures for %x: %d", n.ID[:8], fails) if fails >= maxFindnodeFailures { glog.V(logger.Detail).Infof("Evacuating node %x: %d findnode failures", n.ID[:8], fails) tab.delete(n) } } reply <- tab.bondall(r) }() } } if pendingQueries == 0 { // we have asked all closest nodes, stop the search break } // wait for the next reply for _, n := range <-reply { if n != nil && !seen[n.ID] { seen[n.ID] = true result.push(n, bucketSize) } } pendingQueries-- } return result.entries }
// Run loops and evaluates the contract's code with the given input data func (evm *EVM) Run(contract *Contract, input []byte) (ret []byte, err error) { evm.env.SetDepth(evm.env.Depth() + 1) defer evm.env.SetDepth(evm.env.Depth() - 1) if contract.CodeAddr != nil { if p := Precompiled[contract.CodeAddr.Str()]; p != nil { return evm.RunPrecompiled(p, input, contract) } } // Don't bother with the execution if there's no code. if len(contract.Code) == 0 { return nil, nil } codehash := contract.CodeHash // codehash is used when doing jump dest caching if codehash == (common.Hash{}) { codehash = crypto.Keccak256Hash(contract.Code) } var program *Program if evm.cfg.EnableJit { // If the JIT is enabled check the status of the JIT program, // if it doesn't exist compile a new program in a separate // goroutine or wait for compilation to finish if the JIT is // forced. switch GetProgramStatus(codehash) { case progReady: return RunProgram(GetProgram(codehash), evm.env, contract, input) case progUnknown: if evm.cfg.ForceJit { // Create and compile program program = NewProgram(contract.Code) perr := CompileProgram(program) if perr == nil { return RunProgram(program, evm.env, contract, input) } glog.V(logger.Info).Infoln("error compiling program", err) } else { // create and compile the program. Compilation // is done in a separate goroutine program = NewProgram(contract.Code) go func() { err := CompileProgram(program) if err != nil { glog.V(logger.Info).Infoln("error compiling program", err) return } }() } } } var ( caller = contract.caller code = contract.Code instrCount = 0 op OpCode // current opcode mem = NewMemory() // bound memory stack = newstack() // local stack statedb = evm.env.Db() // current state // For optimisation reason we're using uint64 as the program counter. // It's theoretically possible to go above 2^64. The YP defines the PC to be uint256. Practically much less so feasible. pc = uint64(0) // program counter // jump evaluates and checks whether the given jump destination is a valid one // if valid move the `pc` otherwise return an error. jump = func(from uint64, to *big.Int) error { if !contract.jumpdests.has(codehash, code, to) { nop := contract.GetOp(to.Uint64()) return fmt.Errorf("invalid jump destination (%v) %v", nop, to) } pc = to.Uint64() return nil } newMemSize *big.Int cost *big.Int ) contract.Input = input // User defer pattern to check for an error and, based on the error being nil or not, use all gas and return. defer func() { if err != nil && evm.cfg.Debug { evm.logger.captureState(pc, op, contract.Gas, cost, mem, stack, contract, evm.env.Depth(), err) } }() if glog.V(logger.Debug) { glog.Infof("running byte VM %x\n", codehash[:4]) tstart := time.Now() defer func() { glog.Infof("byte VM %x done. time: %v instrc: %v\n", codehash[:4], time.Since(tstart), instrCount) }() } for ; ; instrCount++ { /* if EnableJit && it%100 == 0 { if program != nil && progStatus(atomic.LoadInt32(&program.status)) == progReady { // move execution fmt.Println("moved", it) glog.V(logger.Info).Infoln("Moved execution to JIT") return runProgram(program, pc, mem, stack, evm.env, contract, input) } } */ // Get the memory location of pc op = contract.GetOp(pc) // calculate the new memory size and gas price for the current executing opcode newMemSize, cost, err = calculateGasAndSize(evm.env, contract, caller, op, statedb, mem, stack) if err != nil { return nil, err } // Use the calculated gas. When insufficient gas is present, use all gas and return an // Out Of Gas error if !contract.UseGas(cost) { return nil, OutOfGasError } // Resize the memory calculated previously mem.Resize(newMemSize.Uint64()) // Add a log message if evm.cfg.Debug { evm.logger.captureState(pc, op, contract.Gas, cost, mem, stack, contract, evm.env.Depth(), nil) } if opPtr := evm.jumpTable[op]; opPtr.valid { if opPtr.fn != nil { opPtr.fn(instruction{}, &pc, evm.env, contract, mem, stack) } else { switch op { case PC: opPc(instruction{data: new(big.Int).SetUint64(pc)}, &pc, evm.env, contract, mem, stack) case JUMP: if err := jump(pc, stack.pop()); err != nil { return nil, err } continue case JUMPI: pos, cond := stack.pop(), stack.pop() if cond.Cmp(common.BigTrue) >= 0 { if err := jump(pc, pos); err != nil { return nil, err } continue } case RETURN: offset, size := stack.pop(), stack.pop() ret := mem.GetPtr(offset.Int64(), size.Int64()) return ret, nil case SUICIDE: opSuicide(instruction{}, nil, evm.env, contract, mem, stack) fallthrough case STOP: // Stop the contract return nil, nil } } } else { return nil, fmt.Errorf("Invalid opcode %x", op) } pc++ } }