예제 #1
0
// upgradeChainDatabase ensures that the chain database stores block split into
// separate header and body entries.
func upgradeChainDatabase(db ethdb.Database) error {
	// Short circuit if the head block is stored already as separate header and body
	data, err := db.Get([]byte("LastBlock"))
	if err != nil {
		return nil
	}
	head := common.BytesToHash(data)

	if block := core.GetBlockByHashOld(db, head); block == nil {
		return nil
	}
	// At least some of the database is still the old format, upgrade (skip the head block!)
	glog.V(logger.Info).Info("Old database detected, upgrading...")

	if db, ok := db.(*ethdb.LDBDatabase); ok {
		blockPrefix := []byte("block-hash-")
		for it := db.NewIterator(); it.Next(); {
			// Skip anything other than a combined block
			if !bytes.HasPrefix(it.Key(), blockPrefix) {
				continue
			}
			// Skip the head block (merge last to signal upgrade completion)
			if bytes.HasSuffix(it.Key(), head.Bytes()) {
				continue
			}
			// Load the block, split and serialize (order!)
			block := core.GetBlockByHashOld(db, common.BytesToHash(bytes.TrimPrefix(it.Key(), blockPrefix)))

			if err := core.WriteTd(db, block.Hash(), block.DeprecatedTd()); err != nil {
				return err
			}
			if err := core.WriteBody(db, block.Hash(), &types.Body{block.Transactions(), block.Uncles()}); err != nil {
				return err
			}
			if err := core.WriteHeader(db, block.Header()); err != nil {
				return err
			}
			if err := db.Delete(it.Key()); err != nil {
				return err
			}
		}
		// Lastly, upgrade the head block, disabling the upgrade mechanism
		current := core.GetBlockByHashOld(db, head)

		if err := core.WriteTd(db, current.Hash(), current.DeprecatedTd()); err != nil {
			return err
		}
		if err := core.WriteBody(db, current.Hash(), &types.Body{current.Transactions(), current.Uncles()}); err != nil {
			return err
		}
		if err := core.WriteHeader(db, current.Header()); err != nil {
			return err
		}
	}
	return nil
}
예제 #2
0
// GetHeadFastBlockHash retrieves the hash of the current canonical head block during
// fast synchronization. The difference between this and GetHeadBlockHash is that
// whereas the last block hash is only updated upon a full block import, the last
// fast hash is updated when importing pre-processed blocks.
func GetHeadFastBlockHash(db ethdb.Database) common.Hash {
	data, _ := db.Get(headFastKey)
	if len(data) == 0 {
		return common.Hash{}
	}
	return common.BytesToHash(data)
}
예제 #3
0
// GetCanonicalHash retrieves a hash assigned to a canonical block number.
func GetCanonicalHash(db ethdb.Database, number uint64) common.Hash {
	data, _ := db.Get(append(blockNumPrefix, big.NewInt(int64(number)).Bytes()...))
	if len(data) == 0 {
		return common.Hash{}
	}
	return common.BytesToHash(data)
}
예제 #4
0
// sets defaults on the config
func setDefaults(cfg *Config) {
	if cfg.Difficulty == nil {
		cfg.Difficulty = new(big.Int)
	}
	if cfg.Time == nil {
		cfg.Time = big.NewInt(time.Now().Unix())
	}
	if cfg.GasLimit == nil {
		cfg.GasLimit = new(big.Int).Set(common.MaxBig)
	}
	if cfg.GasPrice == nil {
		cfg.GasPrice = new(big.Int)
	}
	if cfg.Value == nil {
		cfg.Value = new(big.Int)
	}
	if cfg.BlockNumber == nil {
		cfg.BlockNumber = new(big.Int)
	}
	if cfg.GetHashFn == nil {
		cfg.GetHashFn = func(n uint64) common.Hash {
			return common.BytesToHash(crypto.Sha3([]byte(new(big.Int).SetUint64(n).String())))
		}
	}
}
예제 #5
0
파일: trie.go 프로젝트: efaysal/etherapis
// CommitTo writes all nodes to the given database.
// Nodes are stored with their sha3 hash as the key.
//
// Committing flushes nodes from memory. Subsequent Get calls will
// load nodes from the trie's database. Calling code must ensure that
// the changes made to db are written back to the trie's attached
// database before using the trie.
func (t *Trie) CommitTo(db DatabaseWriter) (root common.Hash, err error) {
	n, err := t.hashRoot(db)
	if err != nil {
		return (common.Hash{}), err
	}
	t.root = n
	return common.BytesToHash(n.(hashNode)), nil
}
예제 #6
0
파일: sync.go 프로젝트: efaysal/etherapis
// children retrieves all the missing children of a state trie entry for future
// retrieval scheduling.
func (s *TrieSync) children(req *request) ([]*request, error) {
	// Gather all the children of the node, irrelevant whether known or not
	type child struct {
		node  *node
		depth int
	}
	children := []child{}

	switch node := (*req.object).(type) {
	case shortNode:
		children = []child{{
			node:  &node.Val,
			depth: req.depth + len(node.Key),
		}}
	case fullNode:
		for i := 0; i < 17; i++ {
			if node[i] != nil {
				children = append(children, child{
					node:  &node[i],
					depth: req.depth + 1,
				})
			}
		}
	default:
		panic(fmt.Sprintf("unknown node: %+v", node))
	}
	// Iterate over the children, and request all unknown ones
	requests := make([]*request, 0, len(children))
	for _, child := range children {
		// Notify any external watcher of a new key/value node
		if req.callback != nil {
			if node, ok := (*child.node).(valueNode); ok {
				if err := req.callback(node, req.hash); err != nil {
					return nil, err
				}
			}
		}
		// If the child references another node, resolve or schedule
		if node, ok := (*child.node).(hashNode); ok {
			// Try to resolve the node from the local database
			blob, _ := s.database.Get(node)
			if local, err := decodeNode(blob); local != nil && err == nil {
				*child.node = local
				continue
			}
			// Locally unknown node, schedule for retrieval
			requests = append(requests, &request{
				object:   child.node,
				hash:     common.BytesToHash(node),
				parents:  []*request{req},
				depth:    child.depth,
				callback: req.callback,
			})
		}
	}
	return requests, nil
}
예제 #7
0
func SaveInfo(info *ContractInfo, filename string) (contenthash common.Hash, err error) {
	infojson, err := json.Marshal(info)
	if err != nil {
		return
	}
	contenthash = common.BytesToHash(crypto.Sha3(infojson))
	err = ioutil.WriteFile(filename, infojson, 0600)
	return
}
예제 #8
0
파일: method.go 프로젝트: efaysal/etherapis
func (e Event) Id() common.Hash {
	types := make([]string, len(e.Inputs))
	i := 0
	for _, input := range e.Inputs {
		types[i] = input.Type.String()
		i++
	}
	return common.BytesToHash(crypto.Sha3([]byte(fmt.Sprintf("%v(%v)", e.Name, strings.Join(types, ",")))))
}
예제 #9
0
// Start Go API. Not important for this version
func (c *Channels) NewChannel(key *ecdsa.PrivateKey, to common.Address, amount, price *big.Int, cb func(*Channel)) (*types.Transaction, error) {
	from := crypto.PubkeyToAddress(key.PublicKey)

	data, err := c.abi.Pack("createChannel", to, price)
	if err != nil {
		return nil, err
	}

	statedb, err := c.blockchain.State()
	if err != nil {
		return nil, err
	}

	transaction, err := types.NewTransaction(statedb.GetNonce(from), contractAddress, amount, big.NewInt(250000), big.NewInt(50000000000), data).SignECDSA(key)
	if err != nil {
		return nil, err
	}

	evId := c.abi.Events["NewChannel"].Id()
	filter := filters.New(c.db)
	filter.SetAddresses([]common.Address{contractAddress})
	filter.SetTopics([][]common.Hash{ // TODO refactor, helper
		[]common.Hash{evId},
		[]common.Hash{from.Hash()},
		[]common.Hash{to.Hash()},
	})
	filter.SetBeginBlock(0)
	filter.SetEndBlock(-1)
	filter.LogsCallback = func(logs vm.Logs) {
		// tere should really be only one log. TODO this part
		log := logs[0]

		// TODO: do to and from validation here
		/*
			from := log.Topics[1]
			to := log.Topics[2]
		*/
		channelId := common.BytesToHash(log.Data[0:31])
		nonce := common.BytesToBig(log.Data[31:])

		c.channelMu.Lock()
		defer c.channelMu.Unlock()

		channel, exist := c.channels[channelId]
		if !exist {
			channel = NewChannel(c, channelId, from, to, nonce)
			c.channels[channelId] = channel
		}
		cb(channel)
	}

	c.filters.Add(filter)

	return transaction, nil
}
예제 #10
0
파일: queue.go 프로젝트: efaysal/etherapis
// DeliverNodeData injects a node state data retrieval response into the queue.
// The method returns the number of node state entries originally requested, and
// the number of them actually accepted from the delivery.
func (q *queue) DeliverNodeData(id string, data [][]byte, callback func(error, int)) (int, error) {
	q.lock.Lock()
	defer q.lock.Unlock()

	// Short circuit if the data was never requested
	request := q.statePendPool[id]
	if request == nil {
		return 0, errNoFetchesPending
	}
	stateReqTimer.UpdateSince(request.Time)
	delete(q.statePendPool, id)

	// If no data was retrieved, mark their hashes as unavailable for the origin peer
	if len(data) == 0 {
		for hash, _ := range request.Hashes {
			request.Peer.MarkLacking(hash)
		}
	}
	// Iterate over the downloaded data and verify each of them
	accepted, errs := 0, make([]error, 0)
	process := []trie.SyncResult{}
	for _, blob := range data {
		// Skip any state trie entires that were not requested
		hash := common.BytesToHash(crypto.Sha3(blob))
		if _, ok := request.Hashes[hash]; !ok {
			errs = append(errs, fmt.Errorf("non-requested state data %x", hash))
			continue
		}
		// Inject the next state trie item into the processing queue
		process = append(process, trie.SyncResult{hash, blob})
		accepted++

		delete(request.Hashes, hash)
		delete(q.stateTaskPool, hash)
	}
	// Start the asynchronous node state data injection
	atomic.AddInt32(&q.stateProcessors, 1)
	go func() {
		defer atomic.AddInt32(&q.stateProcessors, -1)
		q.deliverNodeData(process, callback)
	}()
	// Return all failed or missing fetches to the queue
	for hash, index := range request.Hashes {
		q.stateTaskQueue.Push(hash, float32(index))
	}
	// If none of the data items were good, it's a stale delivery
	switch {
	case len(errs) == 0:
		return accepted, nil
	case len(errs) == len(request.Hashes):
		return accepted, errStaleDelivery
	default:
		return accepted, fmt.Errorf("multiple failures: %v", errs)
	}
}
예제 #11
0
파일: agent.go 프로젝트: efaysal/etherapis
func (self *CpuAgent) mine(work *Work, stop <-chan struct{}) {
	glog.V(logger.Debug).Infof("(re)started agent[%d]. mining...\n", self.index)

	// Mine
	nonce, mixDigest := self.pow.Search(work.Block, stop, self.index)
	if nonce != 0 {
		block := work.Block.WithMiningResult(nonce, common.BytesToHash(mixDigest))
		self.returnCh <- &Result{work, block}
	} else {
		self.returnCh <- nil
	}
}
예제 #12
0
파일: api.go 프로젝트: efaysal/etherapis
// Register registers a new content hash in the registry.
func (api *PrivateRegistarAPI) Register(sender common.Address, addr common.Address, contentHashHex string) (bool, error) {
	block := api.be.bc.CurrentBlock()
	state, err := state.New(block.Root(), api.be.chainDb)
	if err != nil {
		return false, err
	}

	codeb := state.GetCode(addr)
	codeHash := common.BytesToHash(crypto.Sha3(codeb))
	contentHash := common.HexToHash(contentHashHex)

	_, err = registrar.New(api.be).SetHashToHash(sender, codeHash, contentHash)
	return err == nil, err
}
예제 #13
0
func (a *RemoteAgent) GetWork() ([3]string, error) {
	a.mu.Lock()
	defer a.mu.Unlock()

	var res [3]string

	if a.currentWork != nil {
		block := a.currentWork.Block

		res[0] = block.HashNoNonce().Hex()
		seedHash, _ := ethash.GetSeedHash(block.NumberU64())
		res[1] = common.BytesToHash(seedHash).Hex()
		// Calculate the "target" to be returned to the external miner
		n := big.NewInt(1)
		n.Lsh(n, 255)
		n.Div(n, block.Difficulty())
		n.Lsh(n, 1)
		res[2] = common.BytesToHash(n.Bytes()).Hex()

		a.work[block.HashNoNonce()] = a.currentWork
		return res, nil
	}
	return res, errors.New("No work available yet, don't panic.")
}
예제 #14
0
파일: vm.go 프로젝트: efaysal/etherapis
// log emits a log event to the environment for each opcode encountered. This is not to be confused with the
// LOG* opcode.
func (self *Vm) log(pc uint64, op OpCode, gas, cost *big.Int, memory *Memory, stack *stack, contract *Contract, err error) {
	if Debug {
		mem := make([]byte, len(memory.Data()))
		copy(mem, memory.Data())

		stck := make([]*big.Int, len(stack.Data()))
		for i, item := range stack.Data() {
			stck[i] = new(big.Int).Set(item)
		}
		storage := make(map[common.Hash][]byte)
		contract.self.EachStorage(func(k, v []byte) {
			storage[common.BytesToHash(k)] = v
		})
		self.env.AddStructLog(StructLog{pc, op, new(big.Int).Set(gas), cost, mem, stck, storage, err})
	}
}
예제 #15
0
파일: abi.go 프로젝트: efaysal/etherapis
// toGoType parses the input and casts it to the proper type defined by the ABI
// argument in t.
func toGoType(t Argument, input []byte) interface{} {
	switch t.Type.T {
	case IntTy:
		return common.BytesToBig(input)
	case UintTy:
		return common.BytesToBig(input)
	case BoolTy:
		return common.BytesToBig(input).Uint64() > 0
	case AddressTy:
		return common.BytesToAddress(input)
	case HashTy:
		return common.BytesToHash(input)
	case BytesTy:
		return input
	}
	return nil
}
예제 #16
0
파일: trie.go 프로젝트: efaysal/etherapis
func (t *Trie) resolveHash(n hashNode, prefix, suffix []byte) (node, error) {
	if v, ok := globalCache.Get(n); ok {
		return v, nil
	}
	enc, err := t.db.Get(n)
	if err != nil || enc == nil {
		return nil, &MissingNodeError{
			RootHash:  t.originalRoot,
			NodeHash:  common.BytesToHash(n),
			Key:       compactHexEncode(append(prefix, suffix...)),
			PrefixLen: len(prefix),
			SuffixLen: len(suffix),
		}
	}
	dec := mustDecodeNode(n, enc)
	if dec != nil {
		globalCache.Put(n, dec)
	}
	return dec, nil
}
예제 #17
0
파일: sync.go 프로젝트: efaysal/etherapis
// NewStateSync create a new state trie download scheduler.
func NewStateSync(root common.Hash, database ethdb.Database) *StateSync {
	var syncer *trie.TrieSync

	callback := func(leaf []byte, parent common.Hash) error {
		var obj struct {
			Nonce    uint64
			Balance  *big.Int
			Root     common.Hash
			CodeHash []byte
		}
		if err := rlp.Decode(bytes.NewReader(leaf), &obj); err != nil {
			return err
		}
		syncer.AddSubTrie(obj.Root, 64, parent, nil)
		syncer.AddRawEntry(common.BytesToHash(obj.CodeHash), 64, parent)

		return nil
	}
	syncer = trie.NewTrieSync(root, database, callback)
	return (*StateSync)(syncer)
}
예제 #18
0
// also called by admin.contractInfo.get
func FetchDocsForContract(contractAddress string, xeth *xeth.XEth, client *httpclient.HTTPClient) (content []byte, err error) {
	// retrieve contract hash from state
	codehex := xeth.CodeAt(contractAddress)
	codeb := xeth.CodeAtBytes(contractAddress)

	if codehex == "0x" {
		err = fmt.Errorf("contract (%v) not found", contractAddress)
		return
	}
	codehash := common.BytesToHash(crypto.Sha3(codeb))
	// set up nameresolver with natspecreg + urlhint contract addresses
	reg := registrar.New(xeth)

	// resolve host via HashReg/UrlHint Resolver
	hash, err := reg.HashToHash(codehash)
	if err != nil {
		return
	}
	if client.HasScheme("bzz") {
		content, err = client.Get("bzz://"+hash.Hex()[2:], "")
		if err == nil { // non-fatal
			return
		}
		err = nil
		//falling back to urlhint
	}

	uri, err := reg.HashToUrl(hash)
	if err != nil {
		return
	}

	// get content via http client and authenticate content using hash
	content, err = client.GetAuthContent(uri, hash)
	if err != nil {
		return
	}
	return
}
예제 #19
0
파일: trie.go 프로젝트: efaysal/etherapis
// Hash returns the root hash of the trie. It does not write to the
// database and can be used even if the trie doesn't have one.
func (t *Trie) Hash() common.Hash {
	root, _ := t.hashRoot(nil)
	return common.BytesToHash(root.(hashNode))
}
예제 #20
0
파일: api.go 프로젝트: efaysal/etherapis
func (args *NewFilterArgs) UnmarshalJSON(data []byte) error {
	type input struct {
		From      *rpc.BlockNumber `json:"fromBlock"`
		ToBlock   *rpc.BlockNumber `json:"toBlock"`
		Addresses interface{}      `json:"address"`
		Topics    interface{}      `json:"topics"`
	}

	var raw input
	if err := json.Unmarshal(data, &raw); err != nil {
		return err
	}

	if raw.From == nil {
		args.FromBlock = rpc.LatestBlockNumber
	} else {
		args.FromBlock = *raw.From
	}

	if raw.ToBlock == nil {
		args.ToBlock = rpc.LatestBlockNumber
	} else {
		args.ToBlock = *raw.ToBlock
	}

	args.Addresses = []common.Address{}

	if raw.Addresses != nil {
		// raw.Address can contain a single address or an array of addresses
		var addresses []common.Address

		if strAddrs, ok := raw.Addresses.([]interface{}); ok {
			for i, addr := range strAddrs {
				if strAddr, ok := addr.(string); ok {
					if len(strAddr) >= 2 && strAddr[0] == '0' && (strAddr[1] == 'x' || strAddr[1] == 'X') {
						strAddr = strAddr[2:]
					}
					if decAddr, err := hex.DecodeString(strAddr); err == nil {
						addresses = append(addresses, common.BytesToAddress(decAddr))
					} else {
						fmt.Errorf("invalid address given")
					}
				} else {
					return fmt.Errorf("invalid address on index %d", i)
				}
			}
		} else if singleAddr, ok := raw.Addresses.(string); ok {
			if len(singleAddr) >= 2 && singleAddr[0] == '0' && (singleAddr[1] == 'x' || singleAddr[1] == 'X') {
				singleAddr = singleAddr[2:]
			}
			if decAddr, err := hex.DecodeString(singleAddr); err == nil {
				addresses = append(addresses, common.BytesToAddress(decAddr))
			} else {
				fmt.Errorf("invalid address given")
			}
		} else {
			errors.New("invalid address(es) given")
		}
		args.Addresses = addresses
	}

	topicConverter := func(raw string) (common.Hash, error) {
		if len(raw) == 0 {
			return common.Hash{}, nil
		}

		if len(raw) >= 2 && raw[0] == '0' && (raw[1] == 'x' || raw[1] == 'X') {
			raw = raw[2:]
		}

		if decAddr, err := hex.DecodeString(raw); err == nil {
			return common.BytesToHash(decAddr), nil
		}

		return common.Hash{}, errors.New("invalid topic given")
	}

	// topics is an array consisting of strings or arrays of strings
	if raw.Topics != nil {
		topics, ok := raw.Topics.([]interface{})
		if ok {
			parsedTopics := make([][]common.Hash, len(topics))
			for i, topic := range topics {
				if topic == nil {
					parsedTopics[i] = []common.Hash{common.StringToHash("")}
				} else if strTopic, ok := topic.(string); ok {
					if t, err := topicConverter(strTopic); err != nil {
						return fmt.Errorf("invalid topic on index %d", i)
					} else {
						parsedTopics[i] = []common.Hash{t}
					}
				} else if arrTopic, ok := topic.([]interface{}); ok {
					parsedTopics[i] = make([]common.Hash, len(arrTopic))
					for j := 0; j < len(parsedTopics[i]); i++ {
						if arrTopic[j] == nil {
							parsedTopics[i][j] = common.StringToHash("")
						} else if str, ok := arrTopic[j].(string); ok {
							if t, err := topicConverter(str); err != nil {
								return fmt.Errorf("invalid topic on index %d", i)
							} else {
								parsedTopics[i] = []common.Hash{t}
							}
						} else {
							fmt.Errorf("topic[%d][%d] not a string", i, j)
						}
					}
				} else {
					return fmt.Errorf("topic[%d] invalid", i)
				}
			}
			args.Topics = parsedTopics
		}
	}

	return nil
}
예제 #21
0
func (c *StateObject) getAddr(addr common.Hash) common.Hash {
	var ret []byte
	rlp.DecodeBytes(c.trie.Get(addr[:]), &ret)
	return common.BytesToHash(ret)
}
예제 #22
0
// ChannelId returns the canonical channel name for transactor and beneficiary
func (c *Channels) ChannelId(from, to common.Address) common.Hash {
	return common.BytesToHash(c.abi.Call(c.exec, "makeChannelId", from, to).([]byte))
}