// 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("}") }
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()) } } } }
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) } } }
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 }
// 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 (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 }
func TestUDP_findnode(t *testing.T) { test := newUDPTest(t) defer test.table.Close() // put a few nodes into the table. their exact // distribution shouldn't matter much, altough we need to // take care not to overflow any bucket. targetHash := crypto.Keccak256Hash(testTarget[:]) nodes := &nodesByDistance{target: targetHash} for i := 0; i < bucketSize; i++ { nodes.push(nodeAtDistance(test.table.self.sha, i+2), bucketSize) } test.table.stuff(nodes.entries) // ensure there's a bond with the test node, // findnode won't be accepted otherwise. test.table.db.updateNode(NewNode( PubkeyID(&test.remotekey.PublicKey), test.remoteaddr.IP, uint16(test.remoteaddr.Port), 99, )) // check that closest neighbors are returned. test.packetIn(nil, findnodePacket, &findnode{Target: testTarget, Expiration: futureExp}) expected := test.table.closest(targetHash, bucketSize) waitNeighbors := func(want []*Node) { test.waitPacketOut(func(p *neighbors) { if len(p.Nodes) != len(want) { t.Errorf("wrong number of results: got %d, want %d", len(p.Nodes), bucketSize) } for i := range p.Nodes { if p.Nodes[i].ID != want[i].ID { t.Errorf("result mismatch at %d:\n got: %v\n want: %v", i, p.Nodes[i], expected.entries[i]) } } }) } waitNeighbors(expected.entries[:maxNeighbors]) waitNeighbors(expected.entries[maxNeighbors:]) }
// 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 } var ( codehash = crypto.Keccak256Hash(contract.Code) // codehash is used when doing jump dest caching 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, 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, 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++ } }
"github.com/ethereum/go-ethereum/logger" "github.com/ethereum/go-ethereum/logger/glog" "github.com/ethereum/go-ethereum/rlp" ) const defaultCacheCapacity = 800 var ( // The global cache stores decoded trie nodes by hash as they get loaded. globalCache = newARC(defaultCacheCapacity) // 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) ) // ClearGlobalCache clears the global trie cache func ClearGlobalCache() { globalCache.Clear() } // 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.
// end to end test func TestNatspecE2E(t *testing.T) { t.Skip() tf := testInit(t) defer tf.ethereum.Stop() addr, _ := tf.ethereum.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.xeth.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
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 }