Commit 0af0f0d8 authored by obscuren's avatar obscuren

Merge branch 'release/0.6.3'

parents d761af84 c173e9f4
The MIT License (MIT) Copyright (c) 2013-2014, Jeffrey Wilcke. All rights reserved.
Copyright (c) 2013 Jeffrey Wilcke This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
Permission is hereby granted, free of charge, to any person obtaining a copy This library is distributed in the hope that it will be useful,
of this software and associated documentation files (the "Software"), to deal but WITHOUT ANY WARRANTY; without even the implied warranty of
in the Software without restriction, including without limitation the rights MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell Lesser General Public License for more details.
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in You should have received a copy of the GNU Lesser General Public
all copies or substantial portions of the Software. License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR MA 02110-1301 USA
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
...@@ -6,7 +6,7 @@ Ethereum ...@@ -6,7 +6,7 @@ Ethereum
Ethereum Go Development package (C) Jeffrey Wilcke Ethereum Go Development package (C) Jeffrey Wilcke
Ethereum is currently in its testing phase. The current state is "Proof Ethereum is currently in its testing phase. The current state is "Proof
of Concept 0.6.0". For build instructions see the [Wiki](https://github.com/ethereum/go-ethereum/wiki/Building-Ethereum(Go)). of Concept 0.6.3". For build instructions see the [Wiki](https://github.com/ethereum/go-ethereum/wiki/Building-Ethereum(Go)).
Ethereum Go is split up in several sub packages Please refer to each Ethereum Go is split up in several sub packages Please refer to each
individual package for more information. individual package for more information.
...@@ -15,6 +15,11 @@ individual package for more information. ...@@ -15,6 +15,11 @@ individual package for more information.
3. [ethwire](https://github.com/ethereum/eth-go/tree/master/ethwire) 3. [ethwire](https://github.com/ethereum/eth-go/tree/master/ethwire)
4. [ethdb](https://github.com/ethereum/eth-go/tree/master/ethdb) 4. [ethdb](https://github.com/ethereum/eth-go/tree/master/ethdb)
5. [ethutil](https://github.com/ethereum/eth-go/tree/master/ethutil) 5. [ethutil](https://github.com/ethereum/eth-go/tree/master/ethutil)
6. [ethpipe](https://github.com/ethereum/eth-go/tree/master/ethpipe)
7. [ethvm](https://github.com/ethereum/eth-go/tree/master/ethvm)
8. [ethtrie](https://github.com/ethereum/eth-go/tree/master/ethtrie)
9. [ethreact](https://github.com/ethereum/eth-go/tree/master/ethreact)
10. [ethlog](https://github.com/ethereum/eth-go/tree/master/ethlog)
The [eth](https://github.com/ethereum/eth-go) is the top-level package The [eth](https://github.com/ethereum/eth-go) is the top-level package
of the Ethereum protocol. It functions as the Ethereum bootstrapping and of the Ethereum protocol. It functions as the Ethereum bootstrapping and
...@@ -45,7 +50,7 @@ Contribution ...@@ -45,7 +50,7 @@ Contribution
If you'd like to contribute to Eth please fork, fix, commit and If you'd like to contribute to Eth please fork, fix, commit and
send a pull request. Commits who do not comply with the coding standards send a pull request. Commits who do not comply with the coding standards
are ignored. If you send pull requests make absolute sure that you are ignored (use gofmt!). If you send pull requests make absolute sure that you
commit on the `develop` branch and that you do not merge to master. commit on the `develop` branch and that you do not merge to master.
Commits that are directly based on master are simply ignored. Commits that are directly based on master are simply ignored.
......
package eth
import (
"math"
"math/big"
"sync"
"github.com/ethereum/eth-go/ethchain"
"github.com/ethereum/eth-go/ethutil"
)
type block struct {
peer *Peer
block *ethchain.Block
}
type BlockPool struct {
mut sync.Mutex
eth *Ethereum
hashPool [][]byte
pool map[string]*block
td *big.Int
}
func NewBlockPool(eth *Ethereum) *BlockPool {
return &BlockPool{
eth: eth,
pool: make(map[string]*block),
td: ethutil.Big0,
}
}
func (self *BlockPool) HasLatestHash() bool {
return self.pool[string(self.eth.BlockChain().CurrentBlock.Hash())] != nil
}
func (self *BlockPool) HasCommonHash(hash []byte) bool {
return self.eth.BlockChain().GetBlock(hash) != nil
}
func (self *BlockPool) AddHash(hash []byte) {
if self.pool[string(hash)] == nil {
self.pool[string(hash)] = &block{nil, nil}
self.hashPool = append([][]byte{hash}, self.hashPool...)
}
}
func (self *BlockPool) SetBlock(b *ethchain.Block) {
hash := string(b.Hash())
if self.pool[string(hash)] == nil {
self.pool[hash] = &block{nil, nil}
}
self.pool[hash].block = b
}
func (self *BlockPool) CheckLinkAndProcess(f func(block *ethchain.Block)) bool {
self.mut.Lock()
defer self.mut.Unlock()
if self.IsLinked() {
for i, hash := range self.hashPool {
block := self.pool[string(hash)].block
if block != nil {
f(block)
delete(self.pool, string(hash))
} else {
self.hashPool = self.hashPool[i:]
return false
}
}
return true
}
return false
}
func (self *BlockPool) IsLinked() bool {
if len(self.hashPool) == 0 {
return false
}
block := self.pool[string(self.hashPool[0])].block
if block != nil {
return self.eth.BlockChain().HasBlock(block.PrevHash)
}
return false
}
func (self *BlockPool) Take(amount int, peer *Peer) (hashes [][]byte) {
self.mut.Lock()
defer self.mut.Unlock()
num := int(math.Min(float64(amount), float64(len(self.pool))))
j := 0
for i := 0; i < len(self.hashPool) && j < num; i++ {
hash := string(self.hashPool[i])
if self.pool[hash].peer == nil || self.pool[hash].peer == peer {
self.pool[hash].peer = peer
hashes = append(hashes, self.hashPool[i])
j++
}
}
return
}
...@@ -3,13 +3,14 @@ package ethchain ...@@ -3,13 +3,14 @@ package ethchain
import ( import (
"bytes" "bytes"
"fmt" "fmt"
"math/big"
_ "strconv"
"time"
"github.com/ethereum/eth-go/ethcrypto" "github.com/ethereum/eth-go/ethcrypto"
"github.com/ethereum/eth-go/ethstate" "github.com/ethereum/eth-go/ethstate"
"github.com/ethereum/eth-go/ethtrie" "github.com/ethereum/eth-go/ethtrie"
"github.com/ethereum/eth-go/ethutil" "github.com/ethereum/eth-go/ethutil"
"math/big"
_ "strconv"
"time"
) )
type BlockInfo struct { type BlockInfo struct {
...@@ -63,12 +64,6 @@ type Block struct { ...@@ -63,12 +64,6 @@ type Block struct {
TxSha []byte TxSha []byte
} }
// New block takes a raw encoded string
// XXX DEPRICATED
func NewBlockFromData(raw []byte) *Block {
return NewBlockFromBytes(raw)
}
func NewBlockFromBytes(raw []byte) *Block { func NewBlockFromBytes(raw []byte) *Block {
block := &Block{} block := &Block{}
block.RlpDecode(raw) block.RlpDecode(raw)
...@@ -105,7 +100,7 @@ func CreateBlock(root interface{}, ...@@ -105,7 +100,7 @@ func CreateBlock(root interface{},
} }
block.SetUncles([]*Block{}) block.SetUncles([]*Block{})
block.state = ethstate.NewState(ethtrie.NewTrie(ethutil.Config.Db, root)) block.state = ethstate.New(ethtrie.New(ethutil.Config.Db, root))
return block return block
} }
...@@ -130,40 +125,15 @@ func (block *Block) Transactions() []*Transaction { ...@@ -130,40 +125,15 @@ func (block *Block) Transactions() []*Transaction {
return block.transactions return block.transactions
} }
func (block *Block) PayFee(addr []byte, fee *big.Int) bool {
contract := block.state.GetStateObject(addr)
// If we can't pay the fee return
if contract == nil || contract.Amount.Cmp(fee) < 0 /* amount < fee */ {
fmt.Println("Contract has insufficient funds", contract.Amount, fee)
return false
}
base := new(big.Int)
contract.Amount = base.Sub(contract.Amount, fee)
block.state.Trie.Update(string(addr), string(contract.RlpEncode()))
data := block.state.Trie.Get(string(block.Coinbase))
// Get the ether (Coinbase) and add the fee (gief fee to miner)
account := ethstate.NewStateObjectFromBytes(block.Coinbase, []byte(data))
base = new(big.Int)
account.Amount = base.Add(account.Amount, fee)
//block.state.Trie.Update(string(block.Coinbase), string(ether.RlpEncode()))
block.state.UpdateStateObject(account)
return true
}
func (block *Block) CalcGasLimit(parent *Block) *big.Int { func (block *Block) CalcGasLimit(parent *Block) *big.Int {
if block.Number.Cmp(big.NewInt(0)) == 0 { if block.Number.Cmp(big.NewInt(0)) == 0 {
return ethutil.BigPow(10, 6) return ethutil.BigPow(10, 6)
} }
previous := new(big.Int).Mul(big.NewInt(1023), parent.GasLimit) // ((1024-1) * parent.gasLimit + (gasUsed * 6 / 5)) / 1024
current := new(big.Rat).Mul(new(big.Rat).SetInt(block.GasUsed), big.NewRat(6, 5))
previous := new(big.Int).Mul(big.NewInt(1024-1), parent.GasLimit)
current := new(big.Rat).Mul(new(big.Rat).SetInt(parent.GasUsed), big.NewRat(6, 5))
curInt := new(big.Int).Div(current.Num(), current.Denom()) curInt := new(big.Int).Div(current.Num(), current.Denom())
result := new(big.Int).Add(previous, curInt) result := new(big.Int).Add(previous, curInt)
...@@ -172,19 +142,6 @@ func (block *Block) CalcGasLimit(parent *Block) *big.Int { ...@@ -172,19 +142,6 @@ func (block *Block) CalcGasLimit(parent *Block) *big.Int {
min := big.NewInt(125000) min := big.NewInt(125000)
return ethutil.BigMax(min, result) return ethutil.BigMax(min, result)
/*
base := new(big.Int)
base2 := new(big.Int)
parentGL := bc.CurrentBlock.GasLimit
parentUsed := bc.CurrentBlock.GasUsed
base.Mul(parentGL, big.NewInt(1024-1))
base2.Mul(parentUsed, big.NewInt(6))
base2.Div(base2, big.NewInt(5))
base.Add(base, base2)
base.Div(base, big.NewInt(1024))
*/
} }
func (block *Block) BlockInfo() BlockInfo { func (block *Block) BlockInfo() BlockInfo {
...@@ -252,26 +209,10 @@ func (self *Block) SetReceipts(receipts []*Receipt, txs []*Transaction) { ...@@ -252,26 +209,10 @@ func (self *Block) SetReceipts(receipts []*Receipt, txs []*Transaction) {
func (block *Block) setTransactions(txs []*Transaction) { func (block *Block) setTransactions(txs []*Transaction) {
block.transactions = txs block.transactions = txs
/*
trie := ethtrie.NewTrie(ethutil.Config.Db, "")
for i, tx := range txs {
trie.Update(strconv.Itoa(i), string(tx.RlpEncode()))
}
switch trie.Root.(type) {
case string:
block.TxSha = []byte(trie.Root.(string))
case []byte:
block.TxSha = trie.Root.([]byte)
default:
panic(fmt.Sprintf("invalid root type %T", trie.Root))
}
*/
} }
func CreateTxSha(receipts Receipts) (sha []byte) { func CreateTxSha(receipts Receipts) (sha []byte) {
trie := ethtrie.NewTrie(ethutil.Config.Db, "") trie := ethtrie.New(ethutil.Config.Db, "")
for i, receipt := range receipts { for i, receipt := range receipts {
trie.Update(string(ethutil.NewValue(i).Encode()), string(ethutil.NewValue(receipt.RlpData()).Encode())) trie.Update(string(ethutil.NewValue(i).Encode()), string(ethutil.NewValue(receipt.RlpData()).Encode()))
} }
...@@ -313,7 +254,7 @@ func (block *Block) RlpValueDecode(decoder *ethutil.Value) { ...@@ -313,7 +254,7 @@ func (block *Block) RlpValueDecode(decoder *ethutil.Value) {
block.PrevHash = header.Get(0).Bytes() block.PrevHash = header.Get(0).Bytes()
block.UncleSha = header.Get(1).Bytes() block.UncleSha = header.Get(1).Bytes()
block.Coinbase = header.Get(2).Bytes() block.Coinbase = header.Get(2).Bytes()
block.state = ethstate.NewState(ethtrie.NewTrie(ethutil.Config.Db, header.Get(3).Val)) block.state = ethstate.New(ethtrie.New(ethutil.Config.Db, header.Get(3).Val))
block.TxSha = header.Get(4).Bytes() block.TxSha = header.Get(4).Bytes()
block.Difficulty = header.Get(5).BigInt() block.Difficulty = header.Get(5).BigInt()
block.Number = header.Get(6).BigInt() block.Number = header.Get(6).BigInt()
...@@ -355,7 +296,7 @@ func NewUncleBlockFromValue(header *ethutil.Value) *Block { ...@@ -355,7 +296,7 @@ func NewUncleBlockFromValue(header *ethutil.Value) *Block {
block.PrevHash = header.Get(0).Bytes() block.PrevHash = header.Get(0).Bytes()
block.UncleSha = header.Get(1).Bytes() block.UncleSha = header.Get(1).Bytes()
block.Coinbase = header.Get(2).Bytes() block.Coinbase = header.Get(2).Bytes()
block.state = ethstate.NewState(ethtrie.NewTrie(ethutil.Config.Db, header.Get(3).Val)) block.state = ethstate.New(ethtrie.New(ethutil.Config.Db, header.Get(3).Val))
block.TxSha = header.Get(4).Bytes() block.TxSha = header.Get(4).Bytes()
block.Difficulty = header.Get(5).BigInt() block.Difficulty = header.Get(5).BigInt()
block.Number = header.Get(6).BigInt() block.Number = header.Get(6).BigInt()
......
...@@ -2,11 +2,12 @@ package ethchain ...@@ -2,11 +2,12 @@ package ethchain
import ( import (
"bytes" "bytes"
"math"
"math/big"
"github.com/ethereum/eth-go/ethlog" "github.com/ethereum/eth-go/ethlog"
"github.com/ethereum/eth-go/ethutil" "github.com/ethereum/eth-go/ethutil"
"github.com/ethereum/eth-go/ethwire" "github.com/ethereum/eth-go/ethwire"
"math"
"math/big"
) )
var chainlogger = ethlog.NewLogger("CHAIN") var chainlogger = ethlog.NewLogger("CHAIN")
...@@ -131,7 +132,7 @@ func (bc *BlockChain) FindCanonicalChain(blocks []*Block, commonBlockHash []byte ...@@ -131,7 +132,7 @@ func (bc *BlockChain) FindCanonicalChain(blocks []*Block, commonBlockHash []byte
// Start with the newest block we got, all the way back to the common block we both know // Start with the newest block we got, all the way back to the common block we both know
for _, block := range blocks { for _, block := range blocks {
if bytes.Compare(block.Hash(), commonBlockHash) == 0 { if bytes.Compare(block.Hash(), commonBlockHash) == 0 {
chainlogger.Infoln("[CHAIN] We have found the common parent block, breaking") chainlogger.Infoln("We have found the common parent block, breaking")
break break
} }
chainDifficulty.Add(chainDifficulty, bc.CalculateBlockTD(block)) chainDifficulty.Add(chainDifficulty, bc.CalculateBlockTD(block))
...@@ -144,13 +145,13 @@ func (bc *BlockChain) FindCanonicalChain(blocks []*Block, commonBlockHash []byte ...@@ -144,13 +145,13 @@ func (bc *BlockChain) FindCanonicalChain(blocks []*Block, commonBlockHash []byte
for i := 0; block != nil; block = bc.GetBlock(block.PrevHash) { for i := 0; block != nil; block = bc.GetBlock(block.PrevHash) {
i++ i++
if bytes.Compare(block.Hash(), commonBlockHash) == 0 { if bytes.Compare(block.Hash(), commonBlockHash) == 0 {
chainlogger.Infoln("We have found the common parent block, breaking") chainlogger.Infoln("Found the common parent block")
break break
} }
anOtherBlock := bc.GetBlock(block.PrevHash) anOtherBlock := bc.GetBlock(block.PrevHash)
if anOtherBlock == nil { if anOtherBlock == nil {
// We do not want to count the genesis block for difficulty since that's not being sent // We do not want to count the genesis block for difficulty since that's not being sent
chainlogger.Infoln("At genesis block, breaking") chainlogger.Infoln("Found genesis block. Stop")
break break
} }
curChainDifficulty.Add(curChainDifficulty, bc.CalculateBlockTD(block)) curChainDifficulty.Add(curChainDifficulty, bc.CalculateBlockTD(block))
...@@ -158,11 +159,11 @@ func (bc *BlockChain) FindCanonicalChain(blocks []*Block, commonBlockHash []byte ...@@ -158,11 +159,11 @@ func (bc *BlockChain) FindCanonicalChain(blocks []*Block, commonBlockHash []byte
chainlogger.Infoln("Current chain difficulty:", curChainDifficulty) chainlogger.Infoln("Current chain difficulty:", curChainDifficulty)
if chainDifficulty.Cmp(curChainDifficulty) == 1 { if chainDifficulty.Cmp(curChainDifficulty) == 1 {
chainlogger.Infof("The incoming Chain beat our asses, resetting to block: %x", commonBlockHash) chainlogger.Infof("Resetting to block %x. Changing chain.")
bc.ResetTillBlockHash(commonBlockHash) bc.ResetTillBlockHash(commonBlockHash)
return false return false
} else { } else {
chainlogger.Infoln("Our chain showed the incoming chain who is boss. Ignoring.") chainlogger.Infoln("Current chain is longest chain. Ignoring incoming chain.")
return true return true
} }
} }
...@@ -207,6 +208,26 @@ func (bc *BlockChain) GenesisBlock() *Block { ...@@ -207,6 +208,26 @@ func (bc *BlockChain) GenesisBlock() *Block {
return bc.genesisBlock return bc.genesisBlock
} }
func (self *BlockChain) GetChainHashesFromHash(hash []byte, max uint64) (chain [][]byte) {
block := self.GetBlock(hash)
if block == nil {
return
}
// XXX Could be optimised by using a different database which only holds hashes (i.e., linked list)
for i := uint64(0); i < max; i++ {
chain = append(chain, block.Hash())
if block.Number.Cmp(ethutil.Big0) <= 0 {
break
}
block = self.GetBlock(block.PrevHash)
}
return
}
// Get chain return blocks from hash up to max in RLP format // Get chain return blocks from hash up to max in RLP format
func (bc *BlockChain) GetChainFromHash(hash []byte, max uint64) []interface{} { func (bc *BlockChain) GetChainFromHash(hash []byte, max uint64) []interface{} {
var chain []interface{} var chain []interface{}
...@@ -280,7 +301,7 @@ func AddTestNetFunds(block *Block) { ...@@ -280,7 +301,7 @@ func AddTestNetFunds(block *Block) {
} { } {
codedAddr := ethutil.Hex2Bytes(addr) codedAddr := ethutil.Hex2Bytes(addr)
account := block.state.GetAccount(codedAddr) account := block.state.GetAccount(codedAddr)
account.Amount = ethutil.Big("1606938044258990275541962092341162602522202993782792835301376") //ethutil.BigPow(2, 200) account.Balance = ethutil.Big("1606938044258990275541962092341162602522202993782792835301376") //ethutil.BigPow(2, 200)
block.state.UpdateStateObject(account) block.state.UpdateStateObject(account)
} }
} }
...@@ -289,7 +310,6 @@ func (bc *BlockChain) setLastBlock() { ...@@ -289,7 +310,6 @@ func (bc *BlockChain) setLastBlock() {
data, _ := ethutil.Config.Db.Get([]byte("LastBlock")) data, _ := ethutil.Config.Db.Get([]byte("LastBlock"))
if len(data) != 0 { if len(data) != 0 {
block := NewBlockFromBytes(data) block := NewBlockFromBytes(data)
//info := bc.BlockInfo(block)
bc.CurrentBlock = block bc.CurrentBlock = block
bc.LastBlockHash = block.Hash() bc.LastBlockHash = block.Hash()
bc.LastBlockNumber = block.Number.Uint64() bc.LastBlockNumber = block.Number.Uint64()
...@@ -300,9 +320,8 @@ func (bc *BlockChain) setLastBlock() { ...@@ -300,9 +320,8 @@ func (bc *BlockChain) setLastBlock() {
bc.genesisBlock.state.Trie.Sync() bc.genesisBlock.state.Trie.Sync()
// Prepare the genesis block // Prepare the genesis block
bc.Add(bc.genesisBlock) bc.Add(bc.genesisBlock)
fk := append([]byte("bloom"), bc.genesisBlock.Hash()...)
//chainlogger.Infof("root %x\n", bm.bc.genesisBlock.State().Root) bc.Ethereum.Db().Put(fk, make([]byte, 255))
//bm.bc.genesisBlock.PrintHash()
} }
// Set the last know difficulty (might be 0x0 as initial value, Genesis) // Set the last know difficulty (might be 0x0 as initial value, Genesis)
...@@ -338,6 +357,18 @@ func (bc *BlockChain) GetBlock(hash []byte) *Block { ...@@ -338,6 +357,18 @@ func (bc *BlockChain) GetBlock(hash []byte) *Block {
return NewBlockFromBytes(data) return NewBlockFromBytes(data)
} }
func (self *BlockChain) GetBlockByNumber(num uint64) *Block {
block := self.CurrentBlock
for ; block.Number.Uint64() != num; block = self.GetBlock(block.PrevHash) {
}
if block.Number.Uint64() == 0 && num != 0 {
return nil
}
return block
}
func (bc *BlockChain) BlockInfoByHash(hash []byte) BlockInfo { func (bc *BlockChain) BlockInfoByHash(hash []byte) BlockInfo {
bi := BlockInfo{} bi := BlockInfo{}
data, _ := ethutil.Config.Db.Get(append(hash, []byte("Info")...)) data, _ := ethutil.Config.Db.Get(append(hash, []byte("Info")...))
......
...@@ -3,16 +3,19 @@ package ethchain ...@@ -3,16 +3,19 @@ package ethchain
import ( import (
"container/list" "container/list"
"fmt" "fmt"
"testing"
"github.com/ethereum/eth-go/ethcrypto"
"github.com/ethereum/eth-go/ethdb" "github.com/ethereum/eth-go/ethdb"
"github.com/ethereum/eth-go/ethreact"
"github.com/ethereum/eth-go/ethutil" "github.com/ethereum/eth-go/ethutil"
"github.com/ethereum/eth-go/ethwire" "github.com/ethereum/eth-go/ethwire"
"testing"
) )
// Implement our EthTest Manager // Implement our EthTest Manager
type TestManager struct { type TestManager struct {
stateManager *StateManager stateManager *StateManager
reactor *ethutil.ReactorEngine reactor *ethreact.ReactorEngine
txPool *TxPool txPool *TxPool
blockChain *BlockChain blockChain *BlockChain
...@@ -47,16 +50,24 @@ func (tm *TestManager) StateManager() *StateManager { ...@@ -47,16 +50,24 @@ func (tm *TestManager) StateManager() *StateManager {
return tm.stateManager return tm.stateManager
} }
func (tm *TestManager) Reactor() *ethutil.ReactorEngine { func (tm *TestManager) Reactor() *ethreact.ReactorEngine {
return tm.reactor return tm.reactor
} }
func (tm *TestManager) Broadcast(msgType ethwire.MsgType, data []interface{}) { func (tm *TestManager) Broadcast(msgType ethwire.MsgType, data []interface{}) {
fmt.Println("Broadcast not implemented") fmt.Println("Broadcast not implemented")
} }
func NewTestManager() *TestManager { func (tm *TestManager) ClientIdentity() ethwire.ClientIdentity {
return nil
}
func (tm *TestManager) KeyManager() *ethcrypto.KeyManager {
return nil
}
ethutil.ReadConfig(".ethtest", "/tmp/ethtest", "", "ETH") func (tm *TestManager) Db() ethutil.Database { return nil }
func NewTestManager() *TestManager {
ethutil.ReadConfig(".ethtest", "/tmp/ethtest", "ETH")
db, err := ethdb.NewMemDatabase() db, err := ethdb.NewMemDatabase()
if err != nil { if err != nil {
...@@ -66,7 +77,7 @@ func NewTestManager() *TestManager { ...@@ -66,7 +77,7 @@ func NewTestManager() *TestManager {
ethutil.Config.Db = db ethutil.Config.Db = db
testManager := &TestManager{} testManager := &TestManager{}
testManager.reactor = ethutil.NewReactorEngine() testManager.reactor = ethreact.New()
testManager.txPool = NewTxPool(testManager) testManager.txPool = NewTxPool(testManager)
testManager.blockChain = NewBlockChain(testManager) testManager.blockChain = NewBlockChain(testManager)
......
package ethchain
type BloomFilter struct {
bin []byte
}
func NewBloomFilter(bin []byte) *BloomFilter {
if bin == nil {
bin = make([]byte, 256)
}
return &BloomFilter{
bin: bin,
}
}
func (self *BloomFilter) Set(addr []byte) {
if len(addr) < 8 {
chainlogger.Warnf("err: bloom set to small: %x\n", addr)
return
}
for _, i := range addr[len(addr)-8:] {
self.bin[i] = 1
}
}
func (self *BloomFilter) Search(addr []byte) bool {
if len(addr) < 8 {
chainlogger.Warnf("err: bloom search to small: %x\n", addr)
return false
}
for _, i := range addr[len(addr)-8:] {
if self.bin[i] == 0 {
return false
}
}
return true
}
func (self *BloomFilter) Bin() []byte {
return self.bin
}
package ethchain
import "testing"
func TestBloomFilter(t *testing.T) {
bf := NewBloomFilter(nil)
a := []byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 0}
bf.Set(a)
b := []byte{10, 11, 12, 13, 14, 15, 16, 17, 18, 19}
if bf.Search(a) == false {
t.Error("Expected 'a' to yield true using a bloom filter")
}
if bf.Search(b) {
t.Error("Expected 'b' not to field trie using a bloom filter")
}
}
...@@ -3,6 +3,7 @@ package ethchain ...@@ -3,6 +3,7 @@ package ethchain
import ( import (
"github.com/ethereum/eth-go/ethcrypto" "github.com/ethereum/eth-go/ethcrypto"
"github.com/ethereum/eth-go/ethlog" "github.com/ethereum/eth-go/ethlog"
"github.com/ethereum/eth-go/ethreact"
"github.com/ethereum/eth-go/ethutil" "github.com/ethereum/eth-go/ethutil"
"github.com/obscuren/sha3" "github.com/obscuren/sha3"
"hash" "hash"
...@@ -14,7 +15,7 @@ import ( ...@@ -14,7 +15,7 @@ import (
var powlogger = ethlog.NewLogger("POW") var powlogger = ethlog.NewLogger("POW")
type PoW interface { type PoW interface {
Search(block *Block, reactChan chan ethutil.React) []byte Search(block *Block, reactChan chan ethreact.Event) []byte
Verify(hash []byte, diff *big.Int, nonce []byte) bool Verify(hash []byte, diff *big.Int, nonce []byte) bool
GetHashrate() int64 GetHashrate() int64
} }
...@@ -28,7 +29,7 @@ func (pow *EasyPow) GetHashrate() int64 { ...@@ -28,7 +29,7 @@ func (pow *EasyPow) GetHashrate() int64 {
return pow.HashRate return pow.HashRate
} }
func (pow *EasyPow) Search(block *Block, reactChan chan ethutil.React) []byte { func (pow *EasyPow) Search(block *Block, reactChan chan ethreact.Event) []byte {
r := rand.New(rand.NewSource(time.Now().UnixNano())) r := rand.New(rand.NewSource(time.Now().UnixNano()))
hash := block.HashNoNonce() hash := block.HashNoNonce()
diff := block.Difficulty diff := block.Difficulty
......
package ethchain
import (
"bytes"
"fmt"
"github.com/ethereum/eth-go/ethstate"
"github.com/ethereum/eth-go/ethutil"
"gopkg.in/qml.v1"
)
type data struct {
id, address []byte
}
// Filtering interface
type Filter struct {
eth EthManager
earliest []byte
latest []byte
skip int
from, to [][]byte
max int
altered []data
}
// Create a new filter which uses a bloom filter on blocks to figure out whether a particular block
// is interesting or not.
func NewFilter(eth EthManager) *Filter {
return &Filter{eth: eth}
}
func NewFilterFromMap(object map[string]interface{}, eth EthManager) *Filter {
filter := NewFilter(eth)
if object["earliest"] != nil {
earliest := object["earliest"]
if e, ok := earliest.(string); ok {
filter.SetEarliestBlock(ethutil.Hex2Bytes(e))
} else {
filter.SetEarliestBlock(earliest)
}
}
if object["latest"] != nil {
latest := object["latest"]
if l, ok := latest.(string); ok {
filter.SetLatestBlock(ethutil.Hex2Bytes(l))
} else {
filter.SetLatestBlock(latest)
}
}
if object["to"] != nil {
filter.AddTo(ethutil.Hex2Bytes(object["to"].(string)))
}
if object["from"] != nil {
filter.AddFrom(ethutil.Hex2Bytes(object["from"].(string)))
}
if object["max"] != nil {
filter.SetMax(object["max"].(int))
}
if object["skip"] != nil {
filter.SetSkip(object["skip"].(int))
}
if object["altered"] != nil {
filter.altered = makeAltered(object["altered"])
}
return filter
}
func (self *Filter) AddAltered(id, address []byte) {
self.altered = append(self.altered, data{id, address})
}
// Set the earliest and latest block for filtering.
// -1 = latest block (i.e., the current block)
// hash = particular hash from-to
func (self *Filter) SetEarliestBlock(earliest interface{}) {
e := ethutil.NewValue(earliest)
// Check for -1 (latest) otherwise assume bytes
if e.Int() == -1 {
self.earliest = self.eth.BlockChain().CurrentBlock.Hash()
} else if e.Len() > 0 {
self.earliest = e.Bytes()
} else {
panic(fmt.Sprintf("earliest has to be either -1 or a valid hash: %v (%T)", e, e.Val))
}
}
func (self *Filter) SetLatestBlock(latest interface{}) {
l := ethutil.NewValue(latest)
// Check for -1 (latest) otherwise assume bytes
if l.Int() == -1 {
self.latest = self.eth.BlockChain().CurrentBlock.Hash()
} else if l.Len() > 0 {
self.latest = l.Bytes()
} else {
panic(fmt.Sprintf("latest has to be either -1 or a valid hash: %v", l))
}
}
func (self *Filter) SetFrom(addr [][]byte) {
self.from = addr
}
func (self *Filter) AddFrom(addr []byte) {
self.from = append(self.from, addr)
}
func (self *Filter) SetTo(addr [][]byte) {
self.to = addr
}
func (self *Filter) AddTo(addr []byte) {
self.to = append(self.to, addr)
}
func (self *Filter) SetMax(max int) {
self.max = max
}
func (self *Filter) SetSkip(skip int) {
self.skip = skip
}
// Run filters messages with the current parameters set
func (self *Filter) Find() []*ethstate.Message {
var messages []*ethstate.Message
block := self.eth.BlockChain().GetBlock(self.latest)
// skip N blocks (useful for pagination)
if self.skip > 0 {
for i := 0; i < i; i++ {
block = self.eth.BlockChain().GetBlock(block.PrevHash)
}
}
// Start block filtering
quit := false
for i := 1; !quit && block != nil; i++ {
// Mark last check
if self.max == i || (len(self.earliest) > 0 && bytes.Compare(block.Hash(), self.earliest) == 0) {
quit = true
}
// Use bloom filtering to see if this block is interesting given the
// current parameters
if self.bloomFilter(block) {
// Get the messages of the block
msgs, err := self.eth.StateManager().GetMessages(block)
if err != nil {
chainlogger.Warnln("err: filter get messages ", err)
break
}
messages = append(messages, self.FilterMessages(msgs)...)
}
block = self.eth.BlockChain().GetBlock(block.PrevHash)
}
return messages
}
func includes(addresses [][]byte, a []byte) (found bool) {
for _, addr := range addresses {
if bytes.Compare(addr, a) == 0 {
return true
}
}
return
}
func (self *Filter) FilterMessages(msgs []*ethstate.Message) []*ethstate.Message {
var messages []*ethstate.Message
// Filter the messages for interesting stuff
for _, message := range msgs {
if len(self.to) > 0 && !includes(self.to, message.To) {
continue
}
if len(self.from) > 0 && !includes(self.from, message.From) {
continue
}
var match bool
if len(self.altered) == 0 {
match = true
}
for _, item := range self.altered {
if len(item.id) > 0 && bytes.Compare(message.To, item.id) != 0 {
continue
}
if len(item.address) > 0 && !includes(message.ChangedAddresses, item.address) {
continue
}
match = true
break
}
if !match {
continue
}
messages = append(messages, message)
}
return messages
}
func (self *Filter) bloomFilter(block *Block) bool {
fk := append([]byte("bloom"), block.Hash()...)
bin, err := self.eth.Db().Get(fk)
if err != nil {
panic(err)
}
bloom := NewBloomFilter(bin)
var fromIncluded, toIncluded bool
if len(self.from) > 0 {
for _, from := range self.from {
if bloom.Search(from) {
fromIncluded = true
break
}
}
} else {
fromIncluded = true
}
if len(self.to) > 0 {
for _, to := range self.to {
if bloom.Search(to) {
toIncluded = true
break
}
}
} else {
toIncluded = true
}
return fromIncluded && toIncluded
}
// Conversion methodn
func mapToData(m map[string]interface{}) (d data) {
if str, ok := m["id"].(string); ok {
d.id = ethutil.Hex2Bytes(str)
}
if str, ok := m["at"].(string); ok {
d.address = ethutil.Hex2Bytes(str)
}
return
}
// data can come in in the following formats:
// ["aabbccdd", {id: "ccddee", at: "11223344"}], "aabbcc", {id: "ccddee", at: "1122"}
func makeAltered(v interface{}) (d []data) {
if str, ok := v.(string); ok {
d = append(d, data{ethutil.Hex2Bytes(str), nil})
} else if obj, ok := v.(map[string]interface{}); ok {
d = append(d, mapToData(obj))
} else if slice, ok := v.([]interface{}); ok {
for _, item := range slice {
d = append(d, makeAltered(item)...)
}
} else if qList, ok := v.(*qml.List); ok {
var s []interface{}
qList.Convert(&s)
fmt.Println(s)
d = makeAltered(s)
} else if qMap, ok := v.(*qml.Map); ok {
var m map[string]interface{}
qMap.Convert(&m)
fmt.Println(m)
d = makeAltered(m)
} else {
panic(fmt.Sprintf("makeAltered err (unknown conversion): %T\n", v))
}
return
}
package ethchain
import "testing"
func TestFilter(t *testing.T) {
filter := NewFilter()
}
package ethchain package ethchain
import ( import (
"math/big"
"github.com/ethereum/eth-go/ethcrypto" "github.com/ethereum/eth-go/ethcrypto"
"github.com/ethereum/eth-go/ethutil" "github.com/ethereum/eth-go/ethutil"
"math/big"
) )
/* /*
...@@ -26,7 +27,8 @@ var GenesisHeader = []interface{}{ ...@@ -26,7 +27,8 @@ var GenesisHeader = []interface{}{
// tx sha // tx sha
"", "",
// Difficulty // Difficulty
ethutil.BigPow(2, 22), //ethutil.BigPow(2, 22),
big.NewInt(4096),
// Number // Number
ethutil.Big0, ethutil.Big0,
// Block minimum gas price // Block minimum gas price
......
...@@ -4,14 +4,16 @@ import ( ...@@ -4,14 +4,16 @@ import (
"bytes" "bytes"
"container/list" "container/list"
"fmt" "fmt"
"math/big"
"sync"
"time"
"github.com/ethereum/eth-go/ethcrypto" "github.com/ethereum/eth-go/ethcrypto"
"github.com/ethereum/eth-go/ethlog" "github.com/ethereum/eth-go/ethlog"
"github.com/ethereum/eth-go/ethreact"
"github.com/ethereum/eth-go/ethstate" "github.com/ethereum/eth-go/ethstate"
"github.com/ethereum/eth-go/ethutil" "github.com/ethereum/eth-go/ethutil"
"github.com/ethereum/eth-go/ethwire" "github.com/ethereum/eth-go/ethwire"
"math/big"
"sync"
"time"
) )
var statelogger = ethlog.NewLogger("STATE") var statelogger = ethlog.NewLogger("STATE")
...@@ -36,13 +38,14 @@ type EthManager interface { ...@@ -36,13 +38,14 @@ type EthManager interface {
BlockChain() *BlockChain BlockChain() *BlockChain
TxPool() *TxPool TxPool() *TxPool
Broadcast(msgType ethwire.MsgType, data []interface{}) Broadcast(msgType ethwire.MsgType, data []interface{})
Reactor() *ethutil.ReactorEngine Reactor() *ethreact.ReactorEngine
PeerCount() int PeerCount() int
IsMining() bool IsMining() bool
IsListening() bool IsListening() bool
Peers() *list.List Peers() *list.List
KeyManager() *ethcrypto.KeyManager KeyManager() *ethcrypto.KeyManager
ClientIdentity() ethwire.ClientIdentity ClientIdentity() ethwire.ClientIdentity
Db() ethutil.Database
} }
type StateManager struct { type StateManager struct {
...@@ -233,7 +236,12 @@ func (sm *StateManager) Process(block *Block, dontReact bool) (err error) { ...@@ -233,7 +236,12 @@ func (sm *StateManager) Process(block *Block, dontReact bool) (err error) {
// Add the block to the chain // Add the block to the chain
sm.bc.Add(block) sm.bc.Add(block)
sm.notifyChanges(state)
// Create a bloom bin for this block
filter := sm.createBloomFilter(state)
// Persist the data
fk := append([]byte("bloom"), block.Hash()...)
sm.Ethereum.Db().Put(fk, filter.Bin())
statelogger.Infof("Added block #%d (%x)\n", block.Number, block.Hash()) statelogger.Infof("Added block #%d (%x)\n", block.Number, block.Hash())
if dontReact == false { if dontReact == false {
...@@ -361,14 +369,56 @@ func (sm *StateManager) Stop() { ...@@ -361,14 +369,56 @@ func (sm *StateManager) Stop() {
sm.bc.Stop() sm.bc.Stop()
} }
func (sm *StateManager) notifyChanges(state *ethstate.State) { // Manifest will handle both creating notifications and generating bloom bin data
for addr, stateObject := range state.Manifest().ObjectChanges { func (sm *StateManager) createBloomFilter(state *ethstate.State) *BloomFilter {
sm.Ethereum.Reactor().Post("object:"+addr, stateObject) bloomf := NewBloomFilter(nil)
/*
for addr, stateObject := range state.Manifest().ObjectChanges {
// Set the bloom filter's bin
bloomf.Set([]byte(addr))
sm.Ethereum.Reactor().Post("object:"+addr, stateObject)
}
*/
for _, msg := range state.Manifest().Messages {
bloomf.Set(msg.To)
bloomf.Set(msg.From)
} }
for stateObjectAddr, mappedObjects := range state.Manifest().StorageChanges { sm.Ethereum.Reactor().Post("messages", state.Manifest().Messages)
for addr, value := range mappedObjects {
sm.Ethereum.Reactor().Post("storage:"+stateObjectAddr+":"+addr, &ethstate.StorageState{[]byte(stateObjectAddr), []byte(addr), value}) /*
for stateObjectAddr, mappedObjects := range state.Manifest().StorageChanges {
for addr, value := range mappedObjects {
// Set the bloom filter's bin
bloomf.Set(ethcrypto.Sha3Bin([]byte(stateObjectAddr + addr)))
sm.Ethereum.Reactor().Post("storage:"+stateObjectAddr+":"+addr, &ethstate.StorageState{[]byte(stateObjectAddr), []byte(addr), value})
}
} }
*/
return bloomf
}
func (sm *StateManager) GetMessages(block *Block) (messages []*ethstate.Message, err error) {
if !sm.bc.HasBlock(block.PrevHash) {
return nil, ParentError(block.PrevHash)
} }
sm.lastAttemptedBlock = block
var (
parent = sm.bc.GetBlock(block.PrevHash)
state = parent.State().Copy()
)
defer state.Reset()
sm.ApplyDiff(state, parent, block)
sm.AccumelateRewards(state, block)
return state.Manifest().Messages, nil
} }
...@@ -2,11 +2,12 @@ package ethchain ...@@ -2,11 +2,12 @@ package ethchain
import ( import (
"fmt" "fmt"
"math/big"
"github.com/ethereum/eth-go/ethstate" "github.com/ethereum/eth-go/ethstate"
"github.com/ethereum/eth-go/ethtrie" "github.com/ethereum/eth-go/ethtrie"
"github.com/ethereum/eth-go/ethutil" "github.com/ethereum/eth-go/ethutil"
"github.com/ethereum/eth-go/ethvm" "github.com/ethereum/eth-go/ethvm"
"math/big"
) )
/* /*
...@@ -94,8 +95,8 @@ func (self *StateTransition) BuyGas() error { ...@@ -94,8 +95,8 @@ func (self *StateTransition) BuyGas() error {
var err error var err error
sender := self.Sender() sender := self.Sender()
if sender.Amount.Cmp(self.tx.GasValue()) < 0 { if sender.Balance.Cmp(self.tx.GasValue()) < 0 {
return fmt.Errorf("Insufficient funds to pre-pay gas. Req %v, has %v", self.tx.GasValue(), sender.Amount) return fmt.Errorf("Insufficient funds to pre-pay gas. Req %v, has %v", self.tx.GasValue(), sender.Balance)
} }
coinbase := self.Coinbase() coinbase := self.Coinbase()
...@@ -178,8 +179,8 @@ func (self *StateTransition) TransitionState() (err error) { ...@@ -178,8 +179,8 @@ func (self *StateTransition) TransitionState() (err error) {
return return
} }
if sender.Amount.Cmp(self.value) < 0 { if sender.Balance.Cmp(self.value) < 0 {
return fmt.Errorf("Insufficient funds to transfer value. Req %v, has %v", self.value, sender.Amount) return fmt.Errorf("Insufficient funds to transfer value. Req %v, has %v", self.value, sender.Balance)
} }
var snapshot *ethstate.State var snapshot *ethstate.State
...@@ -210,6 +211,14 @@ func (self *StateTransition) TransitionState() (err error) { ...@@ -210,6 +211,14 @@ func (self *StateTransition) TransitionState() (err error) {
snapshot = self.state.Copy() snapshot = self.state.Copy()
} }
msg := self.state.Manifest().AddMessage(&ethstate.Message{
To: receiver.Address(), From: sender.Address(),
Input: self.tx.Data,
Origin: sender.Address(),
Block: self.block.Hash(), Timestamp: self.block.Time, Coinbase: self.block.Coinbase, Number: self.block.Number,
Value: self.value,
})
// Process the init code and create 'valid' contract // Process the init code and create 'valid' contract
if IsContractAddr(self.receiver) { if IsContractAddr(self.receiver) {
// Evaluate the initialization script // Evaluate the initialization script
...@@ -217,7 +226,7 @@ func (self *StateTransition) TransitionState() (err error) { ...@@ -217,7 +226,7 @@ func (self *StateTransition) TransitionState() (err error) {
// script section for the state object. // script section for the state object.
self.data = nil self.data = nil
code, err := self.Eval(receiver.Init(), receiver, "init") code, err := self.Eval(msg, receiver.Init(), receiver, "init")
if err != nil { if err != nil {
self.state.Set(snapshot) self.state.Set(snapshot)
...@@ -225,14 +234,17 @@ func (self *StateTransition) TransitionState() (err error) { ...@@ -225,14 +234,17 @@ func (self *StateTransition) TransitionState() (err error) {
} }
receiver.Code = code receiver.Code = code
msg.Output = code
} else { } else {
if len(receiver.Code) > 0 { if len(receiver.Code) > 0 {
_, err = self.Eval(receiver.Code, receiver, "code") ret, err := self.Eval(msg, receiver.Code, receiver, "code")
if err != nil { if err != nil {
self.state.Set(snapshot) self.state.Set(snapshot)
return fmt.Errorf("Error during code execution %v", err) return fmt.Errorf("Error during code execution %v", err)
} }
msg.Output = ret
} }
} }
...@@ -240,8 +252,8 @@ func (self *StateTransition) TransitionState() (err error) { ...@@ -240,8 +252,8 @@ func (self *StateTransition) TransitionState() (err error) {
} }
func (self *StateTransition) transferValue(sender, receiver *ethstate.StateObject) error { func (self *StateTransition) transferValue(sender, receiver *ethstate.StateObject) error {
if sender.Amount.Cmp(self.value) < 0 { if sender.Balance.Cmp(self.value) < 0 {
return fmt.Errorf("Insufficient funds to transfer value. Req %v, has %v", self.value, sender.Amount) return fmt.Errorf("Insufficient funds to transfer value. Req %v, has %v", self.value, sender.Balance)
} }
// Subtract the amount from the senders account // Subtract the amount from the senders account
...@@ -252,12 +264,12 @@ func (self *StateTransition) transferValue(sender, receiver *ethstate.StateObjec ...@@ -252,12 +264,12 @@ func (self *StateTransition) transferValue(sender, receiver *ethstate.StateObjec
return nil return nil
} }
func (self *StateTransition) Eval(script []byte, context *ethstate.StateObject, typ string) (ret []byte, err error) { func (self *StateTransition) Eval(msg *ethstate.Message, script []byte, context *ethstate.StateObject, typ string) (ret []byte, err error) {
var ( var (
transactor = self.Sender() transactor = self.Sender()
state = self.state state = self.state
env = NewEnv(state, self.tx, self.block) env = NewEnv(state, self.tx, self.block)
callerClosure = ethvm.NewClosure(transactor, context, script, self.gas, self.gasPrice) callerClosure = ethvm.NewClosure(msg, transactor, context, script, self.gas, self.gasPrice)
) )
vm := ethvm.New(env) vm := ethvm.New(env)
...@@ -277,7 +289,7 @@ func MakeContract(tx *Transaction, state *ethstate.State) *ethstate.StateObject ...@@ -277,7 +289,7 @@ func MakeContract(tx *Transaction, state *ethstate.State) *ethstate.StateObject
contract := state.NewStateObject(addr) contract := state.NewStateObject(addr)
contract.InitCode = tx.Data contract.InitCode = tx.Data
contract.State = ethstate.NewState(ethtrie.NewTrie(ethutil.Config.Db, "")) contract.State = ethstate.New(ethtrie.New(ethutil.Config.Db, ""))
return contract return contract
} }
......
...@@ -3,10 +3,11 @@ package ethchain ...@@ -3,10 +3,11 @@ package ethchain
import ( import (
"bytes" "bytes"
"fmt" "fmt"
"math/big"
"github.com/ethereum/eth-go/ethcrypto" "github.com/ethereum/eth-go/ethcrypto"
"github.com/ethereum/eth-go/ethutil" "github.com/ethereum/eth-go/ethutil"
"github.com/obscuren/secp256k1-go" "github.com/obscuren/secp256k1-go"
"math/big"
) )
var ContractAddr = []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} var ContractAddr = []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
...@@ -130,7 +131,7 @@ func (tx *Transaction) RlpData() interface{} { ...@@ -130,7 +131,7 @@ func (tx *Transaction) RlpData() interface{} {
// TODO Remove prefixing zero's // TODO Remove prefixing zero's
return append(data, tx.v, tx.r, tx.s) return append(data, tx.v, new(big.Int).SetBytes(tx.r).Bytes(), new(big.Int).SetBytes(tx.s).Bytes())
} }
func (tx *Transaction) RlpValue() *ethutil.Value { func (tx *Transaction) RlpValue() *ethutil.Value {
......
...@@ -4,11 +4,12 @@ import ( ...@@ -4,11 +4,12 @@ import (
"bytes" "bytes"
"container/list" "container/list"
"fmt" "fmt"
"math/big"
"sync"
"github.com/ethereum/eth-go/ethlog" "github.com/ethereum/eth-go/ethlog"
"github.com/ethereum/eth-go/ethstate" "github.com/ethereum/eth-go/ethstate"
"github.com/ethereum/eth-go/ethwire" "github.com/ethereum/eth-go/ethwire"
"math/big"
"sync"
) )
var txplogger = ethlog.NewLogger("TXP") var txplogger = ethlog.NewLogger("TXP")
...@@ -91,78 +92,6 @@ func (pool *TxPool) addTransaction(tx *Transaction) { ...@@ -91,78 +92,6 @@ func (pool *TxPool) addTransaction(tx *Transaction) {
pool.Ethereum.Broadcast(ethwire.MsgTxTy, []interface{}{tx.RlpData()}) pool.Ethereum.Broadcast(ethwire.MsgTxTy, []interface{}{tx.RlpData()})
} }
/*
// Process transaction validates the Tx and processes funds from the
// sender to the recipient.
func (pool *TxPool) ProcessTransaction(tx *Transaction, state *State, toContract bool) (gas *big.Int, err error) {
fmt.Printf("state root before update %x\n", state.Root())
defer func() {
if r := recover(); r != nil {
txplogger.Infoln(r)
err = fmt.Errorf("%v", r)
}
}()
gas = new(big.Int)
addGas := func(g *big.Int) { gas.Add(gas, g) }
addGas(GasTx)
// Get the sender
sender := state.GetAccount(tx.Sender())
if sender.Nonce != tx.Nonce {
err = NonceError(tx.Nonce, sender.Nonce)
return
}
sender.Nonce += 1
defer func() {
//state.UpdateStateObject(sender)
// Notify all subscribers
pool.Ethereum.Reactor().Post("newTx:post", tx)
}()
txTotalBytes := big.NewInt(int64(len(tx.Data)))
txTotalBytes.Div(txTotalBytes, ethutil.Big32)
addGas(new(big.Int).Mul(txTotalBytes, GasSStore))
rGas := new(big.Int).Set(gas)
rGas.Mul(gas, tx.GasPrice)
// Make sure there's enough in the sender's account. Having insufficient
// funds won't invalidate this transaction but simple ignores it.
totAmount := new(big.Int).Add(tx.Value, rGas)
if sender.Amount.Cmp(totAmount) < 0 {
err = fmt.Errorf("[TXPL] Insufficient amount in sender's (%x) account", tx.Sender())
return
}
state.UpdateStateObject(sender)
fmt.Printf("state root after sender update %x\n", state.Root())
// Get the receiver
receiver := state.GetAccount(tx.Recipient)
// Send Tx to self
if bytes.Compare(tx.Recipient, tx.Sender()) == 0 {
// Subtract the fee
sender.SubAmount(rGas)
} else {
// Subtract the amount from the senders account
sender.SubAmount(totAmount)
// Add the amount to receivers account which should conclude this transaction
receiver.AddAmount(tx.Value)
state.UpdateStateObject(receiver)
fmt.Printf("state root after receiver update %x\n", state.Root())
}
txplogger.Infof("[TXPL] Processed Tx %x\n", tx.Hash())
return
}
*/
func (pool *TxPool) ValidateTransaction(tx *Transaction) error { func (pool *TxPool) ValidateTransaction(tx *Transaction) error {
// Get the last block so we can retrieve the sender and receiver from // Get the last block so we can retrieve the sender and receiver from
// the merkle trie // the merkle trie
...@@ -183,7 +112,7 @@ func (pool *TxPool) ValidateTransaction(tx *Transaction) error { ...@@ -183,7 +112,7 @@ func (pool *TxPool) ValidateTransaction(tx *Transaction) error {
totAmount := new(big.Int).Set(tx.Value) totAmount := new(big.Int).Set(tx.Value)
// Make sure there's enough in the sender's account. Having insufficient // Make sure there's enough in the sender's account. Having insufficient
// funds won't invalidate this transaction but simple ignores it. // funds won't invalidate this transaction but simple ignores it.
if sender.Amount.Cmp(totAmount) < 0 { if sender.Balance.Cmp(totAmount) < 0 {
return fmt.Errorf("[TXPL] Insufficient amount in sender's (%x) account", tx.Sender()) return fmt.Errorf("[TXPL] Insufficient amount in sender's (%x) account", tx.Sender())
} }
......
package ethchain package ethchain
import ( import (
"github.com/ethereum/eth-go/ethstate"
"math/big" "math/big"
"github.com/ethereum/eth-go/ethstate"
) )
type VMEnv struct { type VMEnv struct {
...@@ -25,5 +26,6 @@ func (self *VMEnv) PrevHash() []byte { return self.block.PrevHash } ...@@ -25,5 +26,6 @@ func (self *VMEnv) PrevHash() []byte { return self.block.PrevHash }
func (self *VMEnv) Coinbase() []byte { return self.block.Coinbase } func (self *VMEnv) Coinbase() []byte { return self.block.Coinbase }
func (self *VMEnv) Time() int64 { return self.block.Time } func (self *VMEnv) Time() int64 { return self.block.Time }
func (self *VMEnv) Difficulty() *big.Int { return self.block.Difficulty } func (self *VMEnv) Difficulty() *big.Int { return self.block.Difficulty }
func (self *VMEnv) BlockHash() []byte { return self.block.Hash() }
func (self *VMEnv) Value() *big.Int { return self.tx.Value } func (self *VMEnv) Value() *big.Int { return self.tx.Value }
func (self *VMEnv) State() *ethstate.State { return self.state } func (self *VMEnv) State() *ethstate.State { return self.state }
...@@ -2,40 +2,9 @@ package ethcrypto ...@@ -2,40 +2,9 @@ package ethcrypto
import ( import (
"fmt" "fmt"
"io/ioutil"
"os"
"path"
"path/filepath"
"strconv" "strconv"
"strings"
) )
func InitWords(wordsPath string) {
filename := path.Join(wordsPath, "mnemonic.words.lst")
if _, err := os.Stat(filename); os.IsNotExist(err) {
fmt.Printf("reading mnemonic word list file from supplied path not found. Looked in %s. Trying next option.\n", filename)
dir := path.Join(os.Getenv("GOPATH"), "src", "github.com", "ethereum", "eth-go", "ethcrypto")
filename = path.Join(dir, "mnemonic.words.lst")
if _, err := os.Stat(filename); os.IsNotExist(err) {
fmt.Printf("reading mnemonic word list file 'mnemonic.words.lst' from source folder failed: %s.\n", filename)
dir, err := filepath.Abs(filepath.Dir(os.Args[0]))
if err != nil {
panic(fmt.Errorf("problem getting current folder: ", err))
}
filename = path.Join(dir, "mnemonic.words.lst")
}
}
content, err := ioutil.ReadFile(filename)
if err != nil {
panic(fmt.Errorf("All options for finding the mnemonic word list file 'mnemonic.words.lst' failed: ", err))
}
words = strings.Split(string(content), "\n")
}
var words []string
// TODO: See if we can refactor this into a shared util lib if we need it multiple times // TODO: See if we can refactor this into a shared util lib if we need it multiple times
func IndexOf(slice []string, value string) int64 { func IndexOf(slice []string, value string) int64 {
for p, v := range slice { for p, v := range slice {
...@@ -48,7 +17,7 @@ func IndexOf(slice []string, value string) int64 { ...@@ -48,7 +17,7 @@ func IndexOf(slice []string, value string) int64 {
func MnemonicEncode(message string) []string { func MnemonicEncode(message string) []string {
var out []string var out []string
n := int64(len(words)) n := int64(len(MnemonicWords))
for i := 0; i < len(message); i += (len(message) / 8) { for i := 0; i < len(message); i += (len(message) / 8) {
x := message[i : i+8] x := message[i : i+8]
...@@ -56,22 +25,22 @@ func MnemonicEncode(message string) []string { ...@@ -56,22 +25,22 @@ func MnemonicEncode(message string) []string {
w1 := (bit % n) w1 := (bit % n)
w2 := ((bit / n) + w1) % n w2 := ((bit / n) + w1) % n
w3 := ((bit / n / n) + w2) % n w3 := ((bit / n / n) + w2) % n
out = append(out, words[w1], words[w2], words[w3]) out = append(out, MnemonicWords[w1], MnemonicWords[w2], MnemonicWords[w3])
} }
return out return out
} }
func MnemonicDecode(wordsar []string) string { func MnemonicDecode(wordsar []string) string {
var out string var out string
n := int64(len(words)) n := int64(len(MnemonicWords))
for i := 0; i < len(wordsar); i += 3 { for i := 0; i < len(wordsar); i += 3 {
word1 := wordsar[i] word1 := wordsar[i]
word2 := wordsar[i+1] word2 := wordsar[i+1]
word3 := wordsar[i+2] word3 := wordsar[i+2]
w1 := IndexOf(words, word1) w1 := IndexOf(MnemonicWords, word1)
w2 := IndexOf(words, word2) w2 := IndexOf(MnemonicWords, word2)
w3 := IndexOf(words, word3) w3 := IndexOf(MnemonicWords, word3)
y := (w2 - w1) % n y := (w2 - w1) % n
z := (w3 - w2) % n z := (w3 - w2) % n
......
This diff is collapsed.
This diff is collapsed.
...@@ -3,24 +3,27 @@ package eth ...@@ -3,24 +3,27 @@ package eth
import ( import (
"container/list" "container/list"
"fmt" "fmt"
"github.com/ethereum/eth-go/ethchain"
"github.com/ethereum/eth-go/ethcrypto"
"github.com/ethereum/eth-go/ethlog"
"github.com/ethereum/eth-go/ethrpc"
"github.com/ethereum/eth-go/ethutil"
"github.com/ethereum/eth-go/ethwire"
"io/ioutil"
"math/rand" "math/rand"
"net" "net"
"net/http"
"strconv" "strconv"
"strings" "strings"
"sync" "sync"
"sync/atomic" "sync/atomic"
"time" "time"
"github.com/ethereum/eth-go/ethchain"
"github.com/ethereum/eth-go/ethcrypto"
"github.com/ethereum/eth-go/ethlog"
"github.com/ethereum/eth-go/ethreact"
"github.com/ethereum/eth-go/ethrpc"
"github.com/ethereum/eth-go/ethutil"
"github.com/ethereum/eth-go/ethwire"
) )
const seedTextFileUri string = "http://www.ethereum.org/servers.poc3.txt" const (
seedTextFileUri string = "http://www.ethereum.org/servers.poc3.txt"
seedNodeAddress = "54.76.56.74:30303"
)
var ethlogger = ethlog.NewLogger("SERV") var ethlogger = ethlog.NewLogger("SERV")
...@@ -41,8 +44,8 @@ type Ethereum struct { ...@@ -41,8 +44,8 @@ type Ethereum struct {
// Channel for shutting down the ethereum // Channel for shutting down the ethereum
shutdownChan chan bool shutdownChan chan bool
quit chan bool quit chan bool
// DB interface // DB interface
//db *ethdb.LDBDatabase
db ethutil.Database db ethutil.Database
// State manager for processing new blocks and managing the over all states // State manager for processing new blocks and managing the over all states
stateManager *ethchain.StateManager stateManager *ethchain.StateManager
...@@ -51,6 +54,8 @@ type Ethereum struct { ...@@ -51,6 +54,8 @@ type Ethereum struct {
txPool *ethchain.TxPool txPool *ethchain.TxPool
// The canonical chain // The canonical chain
blockChain *ethchain.BlockChain blockChain *ethchain.BlockChain
// The block pool
blockPool *BlockPool
// Peers (NYI) // Peers (NYI)
peers *list.List peers *list.List
// Nonce // Nonce
...@@ -73,7 +78,7 @@ type Ethereum struct { ...@@ -73,7 +78,7 @@ type Ethereum struct {
listening bool listening bool
reactor *ethutil.ReactorEngine reactor *ethreact.ReactorEngine
RpcServer *ethrpc.JsonRpcServer RpcServer *ethrpc.JsonRpcServer
...@@ -111,8 +116,9 @@ func New(db ethutil.Database, clientIdentity ethwire.ClientIdentity, keyManager ...@@ -111,8 +116,9 @@ func New(db ethutil.Database, clientIdentity ethwire.ClientIdentity, keyManager
clientIdentity: clientIdentity, clientIdentity: clientIdentity,
isUpToDate: true, isUpToDate: true,
} }
ethereum.reactor = ethutil.NewReactorEngine() ethereum.reactor = ethreact.New()
ethereum.blockPool = NewBlockPool(ethereum)
ethereum.txPool = ethchain.NewTxPool(ethereum) ethereum.txPool = ethchain.NewTxPool(ethereum)
ethereum.blockChain = ethchain.NewBlockChain(ethereum) ethereum.blockChain = ethchain.NewBlockChain(ethereum)
ethereum.stateManager = ethchain.NewStateManager(ethereum) ethereum.stateManager = ethchain.NewStateManager(ethereum)
...@@ -123,7 +129,7 @@ func New(db ethutil.Database, clientIdentity ethwire.ClientIdentity, keyManager ...@@ -123,7 +129,7 @@ func New(db ethutil.Database, clientIdentity ethwire.ClientIdentity, keyManager
return ethereum, nil return ethereum, nil
} }
func (s *Ethereum) Reactor() *ethutil.ReactorEngine { func (s *Ethereum) Reactor() *ethreact.ReactorEngine {
return s.reactor return s.reactor
} }
...@@ -146,6 +152,9 @@ func (s *Ethereum) StateManager() *ethchain.StateManager { ...@@ -146,6 +152,9 @@ func (s *Ethereum) StateManager() *ethchain.StateManager {
func (s *Ethereum) TxPool() *ethchain.TxPool { func (s *Ethereum) TxPool() *ethchain.TxPool {
return s.txPool return s.txPool
} }
func (self *Ethereum) Db() ethutil.Database {
return self.db
}
func (s *Ethereum) ServerCaps() Caps { func (s *Ethereum) ServerCaps() Caps {
return s.serverCaps return s.serverCaps
...@@ -355,6 +364,7 @@ func (s *Ethereum) ReapDeadPeerHandler() { ...@@ -355,6 +364,7 @@ func (s *Ethereum) ReapDeadPeerHandler() {
// Start the ethereum // Start the ethereum
func (s *Ethereum) Start(seed bool) { func (s *Ethereum) Start(seed bool) {
s.reactor.Start()
// Bind to addr and port // Bind to addr and port
ln, err := net.Listen("tcp", ":"+s.Port) ln, err := net.Listen("tcp", ":"+s.Port)
if err != nil { if err != nil {
...@@ -420,22 +430,10 @@ func (s *Ethereum) Seed() { ...@@ -420,22 +430,10 @@ func (s *Ethereum) Seed() {
} }
// Connect to Peer list // Connect to Peer list
s.ProcessPeerList(peers) s.ProcessPeerList(peers)
} else {
// Fallback to servers.poc3.txt
resp, err := http.Get(seedTextFileUri)
if err != nil {
ethlogger.Warnln("Fetching seed failed:", err)
return
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
ethlogger.Warnln("Reading seed failed:", err)
return
}
s.ConnectToPeer(string(body))
} }
// XXX tmp
s.ConnectToPeer(seedNodeAddress)
} }
func (s *Ethereum) peerHandler(listener net.Listener) { func (s *Ethereum) peerHandler(listener net.Listener) {
...@@ -466,6 +464,8 @@ func (s *Ethereum) Stop() { ...@@ -466,6 +464,8 @@ func (s *Ethereum) Stop() {
} }
s.txPool.Stop() s.txPool.Stop()
s.stateManager.Stop() s.stateManager.Stop()
s.reactor.Flush()
s.reactor.Stop()
ethlogger.Infoln("Server stopped") ethlogger.Infoln("Server stopped")
close(s.shutdownChan) close(s.shutdownChan)
......
...@@ -39,7 +39,9 @@ func (msg *logMessage) send(logger LogSystem) { ...@@ -39,7 +39,9 @@ func (msg *logMessage) send(logger LogSystem) {
var logMessages chan (*logMessage) var logMessages chan (*logMessage)
var logSystems []LogSystem var logSystems []LogSystem
var quit chan bool var quit chan chan error
var drained chan bool
var mutex = sync.Mutex{}
type LogLevel uint8 type LogLevel uint8
...@@ -52,34 +54,55 @@ const ( ...@@ -52,34 +54,55 @@ const (
DebugDetailLevel DebugDetailLevel
) )
func dispatch(msg *logMessage) {
for _, logSystem := range logSystems {
if logSystem.GetLogLevel() >= msg.LogLevel {
msg.send(logSystem)
}
}
}
// log messages are dispatched to log writers // log messages are dispatched to log writers
func start() { func start() {
out:
for { for {
select { select {
case status := <-quit:
status <- nil
return
case msg := <-logMessages: case msg := <-logMessages:
for _, logSystem := range logSystems { dispatch(msg)
if logSystem.GetLogLevel() >= msg.LogLevel { default:
msg.send(logSystem) drained <- true // this blocks until a message is sent to the queue
}
}
case <-quit:
break out
} }
} }
} }
// waits until log messages are drained (dispatched to log writers) func send(msg *logMessage) {
func Flush() { logMessages <- msg
quit <- true select {
case <-drained:
default:
}
}
done: func Reset() {
for { mutex.Lock()
defer mutex.Unlock()
if logSystems != nil {
status := make(chan error)
quit <- status
select { select {
case <-logMessages: case <-drained:
default: default:
break done
} }
<-status
}
}
// waits until log messages are drained (dispatched to log writers)
func Flush() {
if logSystems != nil {
<-drained
} }
} }
...@@ -97,7 +120,8 @@ func AddLogSystem(logSystem LogSystem) { ...@@ -97,7 +120,8 @@ func AddLogSystem(logSystem LogSystem) {
defer mutex.Unlock() defer mutex.Unlock()
if logSystems == nil { if logSystems == nil {
logMessages = make(chan *logMessage, 10) logMessages = make(chan *logMessage, 10)
quit = make(chan bool, 1) quit = make(chan chan error, 1)
drained = make(chan bool, 1)
go start() go start()
} }
logSystems = append(logSystems, logSystem) logSystems = append(logSystems, logSystem)
...@@ -106,14 +130,14 @@ func AddLogSystem(logSystem LogSystem) { ...@@ -106,14 +130,14 @@ func AddLogSystem(logSystem LogSystem) {
func (logger *Logger) sendln(level LogLevel, v ...interface{}) { func (logger *Logger) sendln(level LogLevel, v ...interface{}) {
if logMessages != nil { if logMessages != nil {
msg := newPrintlnLogMessage(level, logger.tag, v...) msg := newPrintlnLogMessage(level, logger.tag, v...)
logMessages <- msg send(msg)
} }
} }
func (logger *Logger) sendf(level LogLevel, format string, v ...interface{}) { func (logger *Logger) sendf(level LogLevel, format string, v ...interface{}) {
if logMessages != nil { if logMessages != nil {
msg := newPrintfLogMessage(level, logger.tag, format, v...) msg := newPrintfLogMessage(level, logger.tag, format, v...)
logMessages <- msg send(msg)
} }
} }
......
...@@ -28,8 +28,19 @@ func (t *TestLogSystem) GetLogLevel() LogLevel { ...@@ -28,8 +28,19 @@ func (t *TestLogSystem) GetLogLevel() LogLevel {
return t.level return t.level
} }
func quote(s string) string { func TestLoggerFlush(t *testing.T) {
return fmt.Sprintf("'%s'", s) logger := NewLogger("TEST")
testLogSystem := &TestLogSystem{level: WarnLevel}
AddLogSystem(testLogSystem)
for i := 0; i < 5; i++ {
logger.Errorf(".")
}
Flush()
Reset()
output := testLogSystem.Output
if output != "[TEST] .[TEST] .[TEST] .[TEST] .[TEST] ." {
t.Error("Expected complete logger output '[TEST] .[TEST] .[TEST] .[TEST] .[TEST] .', got ", output)
}
} }
func TestLoggerPrintln(t *testing.T) { func TestLoggerPrintln(t *testing.T) {
...@@ -41,10 +52,11 @@ func TestLoggerPrintln(t *testing.T) { ...@@ -41,10 +52,11 @@ func TestLoggerPrintln(t *testing.T) {
logger.Infoln("info") logger.Infoln("info")
logger.Debugln("debug") logger.Debugln("debug")
Flush() Flush()
Reset()
output := testLogSystem.Output output := testLogSystem.Output
fmt.Println(quote(output)) fmt.Println(quote(output))
if output != "[TEST] error\n[TEST] warn\n" { if output != "[TEST] error\n[TEST] warn\n" {
t.Error("Expected logger output '[TEST] error\\n[TEST] warn\\n', got ", quote(testLogSystem.Output)) t.Error("Expected logger output '[TEST] error\\n[TEST] warn\\n', got ", output)
} }
} }
...@@ -57,10 +69,10 @@ func TestLoggerPrintf(t *testing.T) { ...@@ -57,10 +69,10 @@ func TestLoggerPrintf(t *testing.T) {
logger.Infof("info") logger.Infof("info")
logger.Debugf("debug") logger.Debugf("debug")
Flush() Flush()
Reset()
output := testLogSystem.Output output := testLogSystem.Output
fmt.Println(quote(output))
if output != "[TEST] error to { 2}\n[TEST] warn" { if output != "[TEST] error to { 2}\n[TEST] warn" {
t.Error("Expected logger output '[TEST] error to { 2}\\n[TEST] warn', got ", quote(testLogSystem.Output)) t.Error("Expected logger output '[TEST] error to { 2}\\n[TEST] warn', got ", output)
} }
} }
...@@ -73,13 +85,14 @@ func TestMultipleLogSystems(t *testing.T) { ...@@ -73,13 +85,14 @@ func TestMultipleLogSystems(t *testing.T) {
logger.Errorln("error") logger.Errorln("error")
logger.Warnln("warn") logger.Warnln("warn")
Flush() Flush()
Reset()
output0 := testLogSystem0.Output output0 := testLogSystem0.Output
output1 := testLogSystem1.Output output1 := testLogSystem1.Output
if output0 != "[TEST] error\n" { if output0 != "[TEST] error\n" {
t.Error("Expected logger 0 output '[TEST] error\\n', got ", quote(testLogSystem0.Output)) t.Error("Expected logger 0 output '[TEST] error\\n', got ", output0)
} }
if output1 != "[TEST] error\n[TEST] warn\n" { if output1 != "[TEST] error\n[TEST] warn\n" {
t.Error("Expected logger 1 output '[TEST] error\\n[TEST] warn\\n', got ", quote(testLogSystem1.Output)) t.Error("Expected logger 1 output '[TEST] error\\n[TEST] warn\\n', got ", output1)
} }
} }
...@@ -94,9 +107,8 @@ func TestFileLogSystem(t *testing.T) { ...@@ -94,9 +107,8 @@ func TestFileLogSystem(t *testing.T) {
Flush() Flush()
contents, _ := ioutil.ReadFile(filename) contents, _ := ioutil.ReadFile(filename)
output := string(contents) output := string(contents)
fmt.Println(quote(output))
if output != "[TEST] error to test.log\n[TEST] warn\n" { if output != "[TEST] error to test.log\n[TEST] warn\n" {
t.Error("Expected contents of file 'test.log': '[TEST] error to test.log\\n[TEST] warn\\n', got ", quote(output)) t.Error("Expected contents of file 'test.log': '[TEST] error to test.log\\n[TEST] warn\\n', got ", output)
} else { } else {
os.Remove(filename) os.Remove(filename)
} }
......
This diff is collapsed.
package ethpipe
import "github.com/ethereum/eth-go/ethutil"
var cnfCtr = ethutil.Hex2Bytes("661005d2720d855f1d9976f88bb10c1a3398c77f")
type Config struct {
pipe *Pipe
}
func (self *Config) Get(name string) *Object {
configCtrl := self.pipe.World().safeGet(cnfCtr)
var addr []byte
switch name {
case "NameReg":
addr = []byte{0}
case "DnsReg":
objectAddr := configCtrl.GetStorage(ethutil.BigD([]byte{0}))
domainAddr := (&Object{self.pipe.World().safeGet(objectAddr.Bytes())}).StorageString("DnsReg").Bytes()
return &Object{self.pipe.World().safeGet(domainAddr)}
default:
addr = ethutil.RightPadBytes([]byte(name), 32)
}
objectAddr := configCtrl.GetStorage(ethutil.BigD(addr))
return &Object{self.pipe.World().safeGet(objectAddr.Bytes())}
}
func (self *Config) Exist() bool {
return self.pipe.World().Get(cnfCtr) != nil
}
This diff is collapsed.
This diff is collapsed.
package ethpipe
import (
"github.com/ethereum/eth-go/ethstate"
"github.com/ethereum/eth-go/ethutil"
)
type Object struct {
*ethstate.StateObject
}
func (self *Object) StorageString(str string) *ethutil.Value {
if ethutil.IsHex(str) {
return self.Storage(ethutil.Hex2Bytes(str[2:]))
} else {
return self.Storage(ethutil.RightPadBytes([]byte(str), 32))
}
}
func (self *Object) StorageValue(addr *ethutil.Value) *ethutil.Value {
return self.Storage(addr.Bytes())
}
func (self *Object) Storage(addr []byte) *ethutil.Value {
return self.StateObject.GetStorage(ethutil.BigD(addr))
}
This diff is collapsed.
This diff is collapsed.
package ethpipe
import (
"math/big"
"github.com/ethereum/eth-go/ethchain"
"github.com/ethereum/eth-go/ethstate"
)
type VMEnv struct {
state *ethstate.State
block *ethchain.Block
value *big.Int
sender []byte
}
func NewEnv(state *ethstate.State, block *ethchain.Block, value *big.Int, sender []byte) *VMEnv {
return &VMEnv{
state: state,
block: block,
value: value,
sender: sender,
}
}
func (self *VMEnv) Origin() []byte { return self.sender }
func (self *VMEnv) BlockNumber() *big.Int { return self.block.Number }
func (self *VMEnv) PrevHash() []byte { return self.block.PrevHash }
func (self *VMEnv) Coinbase() []byte { return self.block.Coinbase }
func (self *VMEnv) Time() int64 { return self.block.Time }
func (self *VMEnv) Difficulty() *big.Int { return self.block.Difficulty }
func (self *VMEnv) BlockHash() []byte { return self.block.Hash() }
func (self *VMEnv) Value() *big.Int { return self.value }
func (self *VMEnv) State() *ethstate.State { return self.state }
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment