merge upstream

This commit is contained in:
zelig 2014-07-21 13:26:29 +01:00
commit 1e4af85a38
20 changed files with 404 additions and 161 deletions

View File

@ -6,7 +6,7 @@ Ethereum
Ethereum Go Development package (C) Jeffrey Wilcke
Ethereum is currently in its testing phase. The current state is "Proof
of Concept 0.5.16". For build instructions see the [Wiki](https://github.com/ethereum/go-ethereum/wiki/Building-Ethereum(Go)).
of Concept 0.5.20". 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
individual package for more information.

View File

@ -17,10 +17,16 @@ var powlogger = ethlog.NewLogger("POW")
type PoW interface {
Search(block *Block, reactChan chan ethreact.Event) []byte
Verify(hash []byte, diff *big.Int, nonce []byte) bool
GetHashrate() int64
}
type EasyPow struct {
hash *big.Int
hash *big.Int
HashRate int64
}
func (pow *EasyPow) GetHashrate() int64 {
return pow.HashRate
}
func (pow *EasyPow) Search(block *Block, reactChan chan ethreact.Event) []byte {
@ -40,7 +46,8 @@ func (pow *EasyPow) Search(block *Block, reactChan chan ethreact.Event) []byte {
if i%1234567 == 0 {
elapsed := time.Now().UnixNano() - start
hashes := ((float64(1e9) / float64(elapsed)) * float64(i)) / 1000
powlogger.Infoln("Hashing @", int64(hashes), "khash")
pow.HashRate = int64(hashes)
powlogger.Infoln("Hashing @", int64(pow.HashRate), "khash")
}
sha := ethcrypto.Sha3Bin(big.NewInt(r.Int63()).Bytes())

View File

@ -76,6 +76,8 @@ func (self *State) DeleteStateObject(stateObject *StateObject) {
// Retrieve a state object given my the address. Nil if not found
func (self *State) GetStateObject(addr []byte) *StateObject {
addr = ethutil.Address(addr)
stateObject := self.stateObjects[string(addr)]
if stateObject != nil {
return stateObject
@ -145,7 +147,6 @@ func (self *State) Set(state *State) {
self.trie = state.trie
self.stateObjects = state.stateObjects
//*self = *state
}
func (s *State) Root() interface{} {
@ -173,7 +174,7 @@ func (s *State) Reset() {
func (s *State) Sync() {
// Sync all nested states
for _, stateObject := range s.stateObjects {
s.UpdateStateObject(stateObject)
//s.UpdateStateObject(stateObject)
if stateObject.state == nil {
continue
@ -205,6 +206,8 @@ func (self *State) Update() {
// FIXME trie delete is broken
valid, t2 := ethtrie.ParanoiaCheck(self.trie)
if !valid {
statelogger.Infof("Warn: PARANOIA: Different state root during copy %x vs %x\n", self.trie.Root, t2.Root)
self.trie = t2
}
}
@ -212,9 +215,9 @@ func (self *State) Update() {
// Debug stuff
func (self *State) CreateOutputForDiff() {
for addr, stateObject := range self.stateObjects {
fmt.Printf("0x%x 0x%x 0x%x 0x%x\n", addr, stateObject.state.Root(), stateObject.Amount.Bytes(), stateObject.Nonce)
fmt.Printf("%x %x %x %x\n", addr, stateObject.state.Root(), stateObject.Amount.Bytes(), stateObject.Nonce)
stateObject.state.EachStorage(func(addr string, value *ethutil.Value) {
fmt.Printf("0x%x 0x%x\n", addr, value.Bytes())
fmt.Printf("%x %x\n", addr, value.Bytes())
})
}
}

View File

@ -7,7 +7,6 @@ import (
"github.com/ethereum/eth-go/ethcrypto"
"github.com/ethereum/eth-go/ethlog"
"github.com/ethereum/eth-go/ethreact"
"github.com/ethereum/eth-go/ethtrie"
"github.com/ethereum/eth-go/ethutil"
"github.com/ethereum/eth-go/ethwire"
"math/big"
@ -121,7 +120,10 @@ func (self *StateManager) ProcessTransactions(coinbase *StateObject, state *Stat
done:
for i, tx := range txs {
txGas := new(big.Int).Set(tx.Gas)
st := NewStateTransition(coinbase, tx, state, block)
cb := state.GetStateObject(coinbase.Address())
st := NewStateTransition(cb, tx, state, block)
//fmt.Printf("#%d\n", i+1)
err = st.TransitionState()
if err != nil {
switch {
@ -149,10 +151,17 @@ done:
accumelative := new(big.Int).Set(totalUsedGas.Add(totalUsedGas, txGas))
receipt := &Receipt{tx, ethutil.CopyBytes(state.Root().([]byte)), accumelative}
if i < len(block.Receipts()) {
original := block.Receipts()[i]
if !original.Cmp(receipt) {
return nil, nil, nil, fmt.Errorf("err diff #%d (r) %v ~ %x <=> (c) %v ~ %x (%x)\n", i+1, original.CumulativeGasUsed, original.PostState[0:4], receipt.CumulativeGasUsed, receipt.PostState[0:4], receipt.Tx.Hash())
}
}
receipts = append(receipts, receipt)
handled = append(handled, tx)
if ethutil.Config.Diff {
if ethutil.Config.Diff && ethutil.Config.DiffType == "all" {
state.CreateOutputForDiff()
}
}
@ -188,36 +197,11 @@ func (sm *StateManager) Process(block *Block, dontReact bool) (err error) {
// before that.
defer state.Reset()
if ethutil.Config.Diff {
fmt.Printf("## 0x%x 0x%x ##\n", block.Hash(), block.Number)
if ethutil.Config.Diff && ethutil.Config.DiffType == "all" {
fmt.Printf("## %x %x ##\n", block.Hash(), block.Number)
}
receipts, err := sm.ApplyDiff(state, parent, block)
defer func() {
if err != nil {
if len(receipts) == len(block.Receipts()) {
for i, receipt := range block.Receipts() {
statelogger.Infof("diff (r) %v ~ %x <=> (c) %v ~ %x (%x)\n", receipt.CumulativeGasUsed, receipt.PostState[0:4], receipts[i].CumulativeGasUsed, receipts[i].PostState[0:4], receipt.Tx.Hash())
}
} else {
statelogger.Warnln("Unable to print receipt diff. Length didn't match", len(receipts), "for", len(block.Receipts()))
}
} else {
/*
for i, receipt := range receipts {
gu := new(big.Int)
if i != 0 {
gu.Sub(receipt.CumulativeGasUsed, receipts[i-1].CumulativeGasUsed)
} else {
gu.Set(receipt.CumulativeGasUsed)
}
statelogger.Infof("[r] %v ~ %x (%x)\n", gu, receipt.PostState[0:4], receipt.Tx.Hash())
}
*/
}
}()
_, err = sm.ApplyDiff(state, parent, block)
if err != nil {
return err
}
@ -235,12 +219,14 @@ func (sm *StateManager) Process(block *Block, dontReact bool) (err error) {
return err
}
if ethutil.Config.Paranoia {
valid, _ := ethtrie.ParanoiaCheck(state.trie)
if !valid {
err = fmt.Errorf("PARANOIA: World state trie corruption")
/*
if ethutil.Config.Paranoia {
valid, _ := ethtrie.ParanoiaCheck(state.trie)
if !valid {
err = fmt.Errorf("PARANOIA: World state trie corruption")
}
}
}
*/
if !block.State().Cmp(state) {

View File

@ -15,6 +15,18 @@ func (self Code) String() string {
return strings.Join(Disassemble(self), " ")
}
type Storage map[string]*ethutil.Value
func (self Storage) Copy() Storage {
cpy := make(Storage)
for key, value := range self {
// XXX Do we need a 'value' copy or is this sufficient?
cpy[key] = value
}
return cpy
}
type StateObject struct {
// Address of the object
address []byte
@ -27,7 +39,7 @@ type StateObject struct {
script Code
initScript Code
storage map[string]*ethutil.Value
storage Storage
// Total gas pool is the total amount of gas currently
// left if this object is the coinbase. Gas is directly
@ -41,7 +53,8 @@ type StateObject struct {
}
func (self *StateObject) Reset() {
self.storage = make(map[string]*ethutil.Value)
self.storage = make(Storage)
self.state.Reset()
}
// Converts an transaction in to a state object
@ -62,11 +75,12 @@ func MakeContract(tx *Transaction, state *State) *StateObject {
func NewStateObject(addr []byte) *StateObject {
// This to ensure that it has 20 bytes (and not 0 bytes), thus left or right pad doesn't matter.
address := ethutil.LeftPadBytes(addr, 20)
address := ethutil.Address(addr)
object := &StateObject{address: address, Amount: new(big.Int), gasPool: new(big.Int)}
object.state = NewState(ethtrie.NewTrie(ethutil.Config.Db, ""))
object.storage = make(map[string]*ethutil.Value)
object.storage = make(Storage)
object.gasPool = new(big.Int)
return object
}
@ -79,13 +93,6 @@ func NewContract(address []byte, Amount *big.Int, root []byte) *StateObject {
return contract
}
// Returns a newly created account
func NewAccount(address []byte, amount *big.Int) *StateObject {
account := &StateObject{address: address, Amount: amount, Nonce: 0}
return account
}
func NewStateObjectFromBytes(address, data []byte) *StateObject {
object := &StateObject{address: address}
object.RlpDecode(data)
@ -95,7 +102,7 @@ func NewStateObjectFromBytes(address, data []byte) *StateObject {
func (self *StateObject) MarkForDeletion() {
self.remove = true
statelogger.Infof("%x: #%d %v (deletion)\n", self.Address(), self.Nonce, self.Amount)
statelogger.DebugDetailf("%x: #%d %v (deletion)\n", self.Address(), self.Nonce, self.Amount)
}
func (c *StateObject) GetAddr(addr []byte) *ethutil.Value {
@ -113,36 +120,73 @@ func (self *StateObject) SetStorage(key *big.Int, value *ethutil.Value) {
self.setStorage(key.Bytes(), value)
}
func (self *StateObject) getStorage(key []byte) *ethutil.Value {
k := ethutil.LeftPadBytes(key, 32)
func (self *StateObject) getStorage(k []byte) *ethutil.Value {
key := ethutil.LeftPadBytes(k, 32)
value := self.storage[string(k)]
value := self.storage[string(key)]
if value == nil {
value = self.GetAddr(k)
value = self.GetAddr(key)
self.storage[string(k)] = value
if !value.IsNil() {
self.storage[string(key)] = value
}
}
return value
//return self.GetAddr(key)
}
func (self *StateObject) setStorage(key []byte, value *ethutil.Value) {
k := ethutil.LeftPadBytes(key, 32)
func (self *StateObject) setStorage(k []byte, value *ethutil.Value) {
key := ethutil.LeftPadBytes(k, 32)
self.storage[string(key)] = value.Copy()
self.storage[string(k)] = value
/*
if value.BigInt().Cmp(ethutil.Big0) == 0 {
self.state.trie.Delete(string(key))
return
}
self.SetAddr(key, value)
*/
}
func (self *StateObject) Sync() {
/*
fmt.Println("############# BEFORE ################")
self.state.EachStorage(func(key string, value *ethutil.Value) {
fmt.Printf("%x %x %x\n", self.Address(), []byte(key), value.Bytes())
})
fmt.Printf("%x @:%x\n", self.Address(), self.state.Root())
fmt.Println("#####################################")
*/
for key, value := range self.storage {
if value.BigInt().Cmp(ethutil.Big0) == 0 {
if value.Len() == 0 { // value.BigInt().Cmp(ethutil.Big0) == 0 {
//data := self.getStorage([]byte(key))
//fmt.Printf("deleting %x %x 0x%x\n", self.Address(), []byte(key), data)
self.state.trie.Delete(string(key))
continue
}
self.SetAddr([]byte(key), value)
}
valid, t2 := ethtrie.ParanoiaCheck(self.state.trie)
if !valid {
statelogger.Infof("Warn: PARANOIA: Different state storage root during copy %x vs %x\n", self.state.trie.Root, t2.Root)
self.state.trie = t2
}
/*
fmt.Println("############# AFTER ################")
self.state.EachStorage(func(key string, value *ethutil.Value) {
fmt.Printf("%x %x %x\n", self.Address(), []byte(key), value.Bytes())
})
*/
//fmt.Printf("%x @:%x\n", self.Address(), self.state.Root())
}
func (c *StateObject) GetInstr(pc *big.Int) *ethutil.Value {
if int64(len(c.script)-1) < pc.Int64() {
return ethutil.NewValue(0)
@ -154,13 +198,13 @@ func (c *StateObject) GetInstr(pc *big.Int) *ethutil.Value {
func (c *StateObject) AddAmount(amount *big.Int) {
c.SetAmount(new(big.Int).Add(c.Amount, amount))
statelogger.Infof("%x: #%d %v (+ %v)\n", c.Address(), c.Nonce, c.Amount, amount)
statelogger.Debugf("%x: #%d %v (+ %v)\n", c.Address(), c.Nonce, c.Amount, amount)
}
func (c *StateObject) SubAmount(amount *big.Int) {
c.SetAmount(new(big.Int).Sub(c.Amount, amount))
statelogger.Infof("%x: #%d %v (- %v)\n", c.Address(), c.Nonce, c.Amount, amount)
statelogger.Debugf("%x: #%d %v (- %v)\n", c.Address(), c.Nonce, c.Amount, amount)
}
func (c *StateObject) SetAmount(amount *big.Int) {
@ -222,6 +266,8 @@ func (self *StateObject) Copy() *StateObject {
}
stateObject.script = ethutil.CopyBytes(self.script)
stateObject.initScript = ethutil.CopyBytes(self.initScript)
stateObject.storage = self.storage.Copy()
stateObject.gasPool.Set(self.gasPool)
return stateObject
}
@ -280,6 +326,7 @@ func (c *StateObject) RlpDecode(data []byte) {
c.Amount = decoder.Get(1).BigInt()
c.state = NewState(ethtrie.NewTrie(ethutil.Config.Db, decoder.Get(2).Interface()))
c.storage = make(map[string]*ethutil.Value)
c.gasPool = new(big.Int)
c.ScriptHash = decoder.Get(3).Bytes()

View File

@ -2,8 +2,6 @@ package ethchain
import (
"fmt"
"github.com/ethereum/eth-go/ethtrie"
"github.com/ethereum/eth-go/ethutil"
"math/big"
)
@ -44,7 +42,7 @@ func (self *StateTransition) Coinbase() *StateObject {
return self.cb
}
self.cb = self.state.GetAccount(self.coinbase)
self.cb = self.state.GetOrNewStateObject(self.coinbase)
return self.cb
}
func (self *StateTransition) Sender() *StateObject {
@ -52,7 +50,7 @@ func (self *StateTransition) Sender() *StateObject {
return self.sen
}
self.sen = self.state.GetAccount(self.tx.Sender())
self.sen = self.state.GetOrNewStateObject(self.tx.Sender())
return self.sen
}
@ -65,7 +63,7 @@ func (self *StateTransition) Receiver() *StateObject {
return self.rec
}
self.rec = self.state.GetAccount(self.tx.Recipient)
self.rec = self.state.GetOrNewStateObject(self.tx.Recipient)
return self.rec
}
@ -176,13 +174,16 @@ func (self *StateTransition) TransitionState() (err error) {
return
}
/* FIXME
* If tx goes TO "0", goes OOG during init, reverse changes, but initial endowment should happen. The ether is lost forever
*/
var snapshot *State
if sender.Amount.Cmp(self.value) < 0 {
return fmt.Errorf("Insufficient funds to transfer value. Req %v, has %v", self.value, sender.Amount)
}
var snapshot *State
// If the receiver is nil it's a contract (\0*32).
if tx.CreatesContract() {
// Subtract the (irreversible) amount from the senders account
sender.SubAmount(self.value)
snapshot = self.state.Copy()
// Create a new state object for the contract
@ -191,16 +192,17 @@ func (self *StateTransition) TransitionState() (err error) {
if receiver == nil {
return fmt.Errorf("Unable to create contract")
}
// Add the amount to receivers account which should conclude this transaction
receiver.AddAmount(self.value)
} else {
receiver = self.Receiver()
}
// Transfer value from sender to receiver
if err = self.transferValue(sender, receiver); err != nil {
return
}
// Subtract the amount from the senders account
sender.SubAmount(self.value)
// Add the amount to receivers account which should conclude this transaction
receiver.AddAmount(self.value)
if snapshot == nil {
snapshot = self.state.Copy()
}
@ -275,20 +277,5 @@ func (self *StateTransition) Eval(script []byte, context *StateObject, typ strin
func Call(vm *Vm, closure *Closure, data []byte) (ret []byte, err error) {
ret, _, err = closure.Call(vm, data)
if ethutil.Config.Paranoia {
var (
context = closure.object
trie = context.state.trie
)
valid, t2 := ethtrie.ParanoiaCheck(trie)
if !valid {
// TODO FIXME ASAP
context.state.trie = t2
statelogger.Infoln("Warn: PARANOIA: Different state object roots during copy")
}
}
return
}

View File

@ -227,6 +227,14 @@ func (self *Receipt) String() string {
self.CumulativeGasUsed)
}
func (self *Receipt) Cmp(other *Receipt) bool {
if bytes.Compare(self.PostState, other.PostState) != 0 {
return false
}
return true
}
// Transaction slice type for basic sorting
type Transactions []*Transaction

View File

@ -155,6 +155,15 @@ func (vm *Vm) RunClosure(closure *Closure) (ret []byte, err error) {
// XXX Leave this Println intact. Don't change this to the log system.
// Used for creating diffs between implementations
if vm.logTy == LogTyDiff {
switch op {
case STOP, RETURN, SUICIDE:
closure.object.Sync()
closure.object.state.EachStorage(func(key string, value *ethutil.Value) {
value.Decode()
fmt.Printf("%x %x\n", new(big.Int).SetBytes([]byte(key)).Bytes(), value.Bytes())
})
}
b := pc.Bytes()
if len(b) == 0 {
b = []byte{0}
@ -184,9 +193,9 @@ func (vm *Vm) RunClosure(closure *Closure) (ret []byte, err error) {
var mult *big.Int
y, x := stack.Peekn()
val := closure.GetStorage(x)
if val.IsEmpty() && len(y.Bytes()) > 0 {
if val.BigInt().Cmp(ethutil.Big0) == 0 && len(y.Bytes()) > 0 {
mult = ethutil.Big2
} else if !val.IsEmpty() && len(y.Bytes()) == 0 {
} else if val.BigInt().Cmp(ethutil.Big0) != 0 && len(y.Bytes()) == 0 {
mult = ethutil.Big0
} else {
mult = ethutil.Big1
@ -447,7 +456,7 @@ func (vm *Vm) RunClosure(closure *Closure) (ret []byte, err error) {
case BYTE:
require(2)
val, th := stack.Popn()
if th.Cmp(big.NewInt(32)) < 0 {
if th.Cmp(big.NewInt(32)) < 0 && th.Cmp(big.NewInt(int64(len(val.Bytes())))) < 0 {
byt := big.NewInt(int64(val.Bytes()[th.Int64()]))
stack.Push(byt)
@ -482,7 +491,7 @@ func (vm *Vm) RunClosure(closure *Closure) (ret []byte, err error) {
case ORIGIN:
stack.Push(ethutil.BigD(vm.vars.Origin))
vm.Printf(" => %v", vm.vars.Origin)
vm.Printf(" => %x", vm.vars.Origin)
case CALLER:
caller := closure.caller.Address()
stack.Push(ethutil.BigD(caller))
@ -550,10 +559,10 @@ func (vm *Vm) RunClosure(closure *Closure) (ret []byte, err error) {
}
code := closure.Script[cOff : cOff+l]
fmt.Println("len:", l, "code off:", cOff, "mem off:", mOff)
//fmt.Println("len:", l, "code off:", cOff, "mem off:", mOff)
mem.Set(mOff, l, code)
fmt.Println(Code(mem.Get(mOff, l)))
//fmt.Println(Code(mem.Get(mOff, l)))
case GASPRICE:
stack.Push(closure.Price)
@ -743,6 +752,7 @@ func (vm *Vm) RunClosure(closure *Closure) (ret []byte, err error) {
if closure.object.Amount.Cmp(value) < 0 {
vmlogger.Debugf("Insufficient funds to transfer value. Req %v, has %v", value, closure.object.Amount)
closure.ReturnGas(gas, nil, nil)
stack.Push(ethutil.BigFalse)

View File

@ -6,30 +6,35 @@ import (
"os"
"path"
"path/filepath"
"runtime"
"strconv"
"strings"
)
func InitWords() []string {
_, thisfile, _, _ := runtime.Caller(1)
filename := path.Join(path.Dir(thisfile), "mnemonic.words.lst")
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 'mnemonic.words.lst' from source folder failed, looking in current folder.")
dir, err := filepath.Abs(filepath.Dir(os.Args[0]))
if err != nil {
panic(fmt.Errorf("problem getting current folder: ", 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("reading mnemonic word list file 'mnemonic.words.lst' failed: ", err))
panic(fmt.Errorf("All options for finding the mnemonic word list file 'mnemonic.words.lst' failed: ", err))
}
return strings.Split(string(content), "\n")
words = strings.Split(string(content), "\n")
}
var words = InitWords()
var words []string
// 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 {

View File

@ -81,6 +81,8 @@ type Ethereum struct {
keyManager *ethcrypto.KeyManager
clientIdentity ethwire.ClientIdentity
isUpToDate bool
}
func New(db ethutil.Database, clientIdentity ethwire.ClientIdentity, keyManager *ethcrypto.KeyManager, caps Caps, usePnp bool) (*Ethereum, error) {
@ -108,6 +110,7 @@ func New(db ethutil.Database, clientIdentity ethwire.ClientIdentity, keyManager
nat: nat,
keyManager: keyManager,
clientIdentity: clientIdentity,
isUpToDate: true,
}
ethereum.reactor = ethreact.New()
@ -158,7 +161,7 @@ func (s *Ethereum) IsUpToDate() bool {
upToDate := true
eachPeer(s.peers, func(peer *Peer, e *list.Element) {
if atomic.LoadInt32(&peer.connected) == 1 {
if peer.catchingUp == true {
if peer.catchingUp == true && peer.versionKnown {
upToDate = false
}
}
@ -373,6 +376,7 @@ func (s *Ethereum) Start(seed bool) {
// Start the reaping processes
go s.ReapDeadPeerHandler()
go s.update()
if seed {
s.Seed()
@ -514,3 +518,23 @@ out:
ethlogger.Debugln("succesfully disestablished UPnP port mapping")
}
}
func (self *Ethereum) update() {
upToDateTimer := time.NewTicker(1 * time.Second)
out:
for {
select {
case <-upToDateTimer.C:
if self.IsUpToDate() && !self.isUpToDate {
self.reactor.Post("chainSync", false)
self.isUpToDate = true
} else if !self.IsUpToDate() && self.isUpToDate {
self.reactor.Post("chainSync", true)
self.isUpToDate = false
}
case <-self.quit:
break out
}
}
}

View File

@ -119,7 +119,7 @@ func AddLogSystem(logSystem LogSystem) {
mutex.Lock()
defer mutex.Unlock()
if logSystems == nil {
logMessages = make(chan *logMessage, 5)
logMessages = make(chan *logMessage, 10)
quit = make(chan chan error, 1)
drained = make(chan bool, 1)
go start()

View File

@ -21,28 +21,32 @@ type Miner struct {
block *ethchain.Block
powChan chan []byte
powQuitChan chan ethreact.Event
quitChan chan bool
quitChan chan chan error
}
func NewDefaultMiner(coinbase []byte, ethereum ethchain.EthManager) Miner {
func (self *Miner) GetPow() ethchain.PoW {
return self.pow
}
func NewDefaultMiner(coinbase []byte, ethereum ethchain.EthManager) *Miner {
miner := Miner{
pow: &ethchain.EasyPow{},
ethereum: ethereum,
coinbase: coinbase,
}
// Insert initial TXs in our little miner 'pool'
miner.txs = ethereum.TxPool().Flush()
miner.block = ethereum.BlockChain().NewBlock(miner.coinbase)
return miner
return &miner
}
func (miner *Miner) Start() {
miner.reactChan = make(chan ethreact.Event, 1) // This is the channel that receives 'updates' when ever a new transaction or block comes in
miner.powChan = make(chan []byte, 1) // This is the channel that receives valid sha hashes for a given block
miner.powQuitChan = make(chan ethreact.Event, 1) // This is the channel that can exit the miner thread
miner.quitChan = make(chan bool, 1)
miner.quitChan = make(chan chan error, 1)
// Insert initial TXs in our little miner 'pool'
miner.txs = miner.ethereum.TxPool().Flush()
miner.block = miner.ethereum.BlockChain().NewBlock(miner.coinbase)
// Prepare inital block
//miner.ethereum.StateManager().Prepare(miner.block.State(), miner.block.State())
@ -61,15 +65,17 @@ func (miner *Miner) Start() {
reactor.Subscribe("newTx:pre", miner.powQuitChan)
logger.Infoln("Started")
reactor.Post("miner:start", miner)
}
func (miner *Miner) listener() {
out:
for {
select {
case <-miner.quitChan:
case status := <-miner.quitChan:
logger.Infoln("Stopped")
break out
status <- nil
return
case chanMessage := <-miner.reactChan:
if block, ok := chanMessage.Resource.(*ethchain.Block); ok {
@ -127,7 +133,9 @@ out:
func (miner *Miner) Stop() {
logger.Infoln("Stopping...")
miner.quitChan <- true
status := make(chan error)
miner.quitChan <- status
<-status
reactor := miner.ethereum.Reactor()
reactor.Unsubscribe("newBlock", miner.powQuitChan)
@ -137,6 +145,8 @@ func (miner *Miner) Stop() {
close(miner.powQuitChan)
close(miner.quitChan)
reactor.Post("miner:stop", miner)
}
func (self *Miner) mineNewBlock() {

View File

@ -179,6 +179,19 @@ func FindAddressInNameReg(stateManager *ethchain.StateManager, name string) []by
return nil
}
func FindNameInNameReg(stateManager *ethchain.StateManager, addr []byte) string {
nameReg := EthereumConfig(stateManager).NameReg()
if nameReg != nil {
addr = ethutil.LeftPadBytes(addr, 32)
reg := nameReg.GetStorage(ethutil.BigD(addr))
return strings.TrimRight(reg.Str(), "\x00")
}
return ""
}
func (lib *PEthereum) createTx(key, recipient, valueStr, gasStr, gasPriceStr, scriptStr string) (*PReceipt, error) {
var hash []byte
var contractCreation bool

View File

@ -5,6 +5,7 @@ import (
"fmt"
"github.com/ethereum/eth-go/ethchain"
"github.com/ethereum/eth-go/ethcrypto"
"github.com/ethereum/eth-go/ethtrie"
"github.com/ethereum/eth-go/ethutil"
"strings"
)
@ -46,6 +47,7 @@ type PBlock struct {
Transactions string `json:"transactions"`
Time int64 `json:"time"`
Coinbase string `json:"coinbase"`
Name string `json:"name"`
GasLimit string `json:"gasLimit"`
GasUsed string `json:"gasUsed"`
}
@ -212,6 +214,10 @@ func (c *PStateObject) IsContract() bool {
return false
}
func (self *PStateObject) EachStorage(cb ethtrie.EachCallback) {
self.object.State().EachStorage(cb)
}
type KeyVal struct {
Key string
Value string

View File

@ -5,10 +5,12 @@ import (
"fmt"
"github.com/ethereum/eth-go/ethcrypto"
"github.com/ethereum/eth-go/ethutil"
"reflect"
_ "reflect"
"sync"
)
func __ignore() { fmt.Println("") }
func ParanoiaCheck(t1 *Trie) (bool, *Trie) {
t2 := NewTrie(ethutil.Config.Db, "")
@ -269,8 +271,7 @@ func (t *Trie) getState(node interface{}, key []int) interface{} {
}
// It shouldn't come this far
fmt.Println("getState unexpected return")
return ""
panic("unexpected return")
}
func (t *Trie) getNode(node interface{}) *ethutil.Value {
@ -287,7 +288,9 @@ func (t *Trie) getNode(node interface{}) *ethutil.Value {
return ethutil.NewValueFromBytes([]byte(str))
}
return t.cache.Get(n.Bytes())
data := t.cache.Get(n.Bytes())
return data
}
func (t *Trie) UpdateState(node interface{}, key []int, value string) interface{} {
@ -323,7 +326,8 @@ func (t *Trie) InsertState(node interface{}, key []int, value interface{}) inter
// New node
n := ethutil.NewValue(node)
if node == nil || (n.Type() == reflect.String && (n.Str() == "" || n.Get(0).IsNil())) || n.Len() == 0 {
if node == nil || n.Len() == 0 {
//if node == nil || (n.Type() == reflect.String && (n.Str() == "" || n.Get(0).IsNil())) || n.Len() == 0 {
newNode := []interface{}{CompactEncode(key), value}
return t.Put(newNode)
@ -385,17 +389,22 @@ func (t *Trie) InsertState(node interface{}, key []int, value interface{}) inter
return t.Put(newNode)
}
return ""
panic("unexpected end")
}
func (t *Trie) deleteState(node interface{}, key []int) interface{} {
if len(key) == 0 {
println("<empty ret>")
return ""
}
// New node
n := ethutil.NewValue(node)
if node == nil || (n.Type() == reflect.String && (n.Str() == "" || n.Get(0).IsNil())) || n.Len() == 0 {
//if node == nil || (n.Type() == reflect.String && (n.Str() == "" || n.Get(0).IsNil())) || n.Len() == 0 {
if node == nil || n.Len() == 0 {
//return nil
//fmt.Printf("<empty ret> %x %d\n", n, len(n.Bytes()))
return ""
}
@ -408,10 +417,17 @@ func (t *Trie) deleteState(node interface{}, key []int) interface{} {
// Matching key pair (ie. there's already an object with this key)
if CompareIntSlice(k, key) {
//fmt.Printf("<delete ret> %x\n", v)
return ""
} else if CompareIntSlice(key[:len(k)], k) {
hash := t.deleteState(v, key[len(k):])
child := t.getNode(hash)
/*
if child.IsNil() {
return node
}
*/
var newNode []interface{}
if child.Len() == 2 {
@ -421,6 +437,8 @@ func (t *Trie) deleteState(node interface{}, key []int) interface{} {
newNode = []interface{}{currentNode.Get(0).Str(), hash}
}
//fmt.Printf("%x\n", newNode)
return t.Put(newNode)
} else {
return node
@ -463,10 +481,11 @@ func (t *Trie) deleteState(node interface{}, key []int) interface{} {
newNode = n
}
//fmt.Printf("%x\n", newNode)
return t.Put(newNode)
}
return ""
panic("unexpected return")
}
type TrieIterator struct {

View File

@ -1,16 +1,17 @@
package ethtrie
import (
"bytes"
"encoding/hex"
"encoding/json"
_ "bytes"
_ "encoding/hex"
_ "encoding/json"
"fmt"
"io/ioutil"
"math/rand"
"net/http"
"reflect"
"github.com/ethereum/eth-go/ethutil"
_ "io/ioutil"
_ "math/rand"
_ "net/http"
_ "reflect"
"testing"
"time"
_ "time"
)
const LONG_WORD = "1234567890abcdefghijklmnopqrstuvwxxzABCEFGHIJKLMNOPQRSTUVWXYZ"
@ -42,6 +43,7 @@ func New() (*MemDatabase, *Trie) {
return db, NewTrie(db, "")
}
/*
func TestTrieSync(t *testing.T) {
db, trie := New()
@ -251,8 +253,8 @@ func TestRemote(t *testing.T) {
trie.Update(get(key), get(value))
}
a := NewValue(h(test.Root)).Bytes()
b := NewValue(trie.Root).Bytes()
a := ethutil.NewValue(h(test.Root)).Bytes()
b := ethutil.NewValue(trie.Root).Bytes()
if bytes.Compare(a, b) != 0 {
t.Errorf("%-10s: %x %x", test.Name, a, b)
}
@ -267,12 +269,12 @@ func TestTrieReplay(t *testing.T) {
}
_, trie2 := New()
trie.NewIterator().Each(func(key string, v *Value) {
trie.NewIterator().Each(func(key string, v *ethutil.Value) {
trie2.Update(key, v.Str())
})
a := NewValue(trie.Root).Bytes()
b := NewValue(trie2.Root).Bytes()
a := ethutil.NewValue(trie.Root).Bytes()
b := ethutil.NewValue(trie2.Root).Bytes()
if bytes.Compare(a, b) != 0 {
t.Errorf("%s %x %x\n", test.Name, trie.Root, trie2.Root)
}
@ -329,3 +331,90 @@ func TestRegression(t *testing.T) {
}
}
}
func TestDelete(t *testing.T) {
_, trie := New()
trie.Update("a", "jeffreytestlongstring")
trie.Update("aa", "otherstring")
trie.Update("aaa", "othermorestring")
trie.Update("aabbbbccc", "hithere")
trie.Update("abbcccdd", "hstanoehutnaheoustnh")
trie.Update("rnthaoeuabbcccdd", "hstanoehutnaheoustnh")
trie.Update("rneuabbcccdd", "hstanoehutnaheoustnh")
trie.Update("rneuabboeusntahoeucccdd", "hstanoehutnaheoustnh")
trie.Update("rnxabboeusntahoeucccdd", "hstanoehutnaheoustnh")
trie.Delete("aaboaestnuhbccc")
trie.Delete("a")
trie.Update("a", "nthaonethaosentuh")
trie.Update("c", "shtaosntehua")
trie.Delete("a")
trie.Update("aaaa", "testmegood")
fmt.Println("aa =>", trie.Get("aa"))
_, t2 := New()
trie.NewIterator().Each(func(key string, v *ethutil.Value) {
if key == "aaaa" {
t2.Update(key, v.Str())
} else {
t2.Update(key, v.Str())
}
})
a := ethutil.NewValue(trie.Root).Bytes()
b := ethutil.NewValue(t2.Root).Bytes()
fmt.Printf("o: %x\nc: %x\n", a, b)
}
*/
func TestRndCase(t *testing.T) {
_, trie := New()
data := []struct{ k, v string }{
{"0000000000000000000000000000000000000000000000000000000000000001", "a07573657264617461000000000000000000000000000000000000000000000000"},
{"0000000000000000000000000000000000000000000000000000000000000003", "8453bb5b31"},
{"0000000000000000000000000000000000000000000000000000000000000004", "850218711a00"},
{"0000000000000000000000000000000000000000000000000000000000000005", "9462d7705bd0b3ecbc51a8026a25597cb28a650c79"},
{"0000000000000000000000000000000000000000000000000000000000000010", "947e70f9460402290a3e487dae01f610a1a8218fda"},
{"0000000000000000000000000000000000000000000000000000000000000111", "01"},
{"0000000000000000000000000000000000000000000000000000000000000112", "a053656e6174650000000000000000000000000000000000000000000000000000"},
{"0000000000000000000000000000000000000000000000000000000000000113", "a053656e6174650000000000000000000000000000000000000000000000000000"},
{"53656e6174650000000000000000000000000000000000000000000000000000", "94977e3f62f5e1ed7953697430303a3cfa2b5b736e"},
}
for _, e := range data {
trie.Update(string(ethutil.Hex2Bytes(e.k)), string(ethutil.Hex2Bytes(e.v)))
}
fmt.Printf("root after update %x\n", trie.Root)
trie.NewIterator().Each(func(k string, v *ethutil.Value) {
fmt.Printf("%x %x\n", k, v.Bytes())
})
data = []struct{ k, v string }{
{"0000000000000000000000000000000000000000000000000000000000000112", ""},
{"436974697a656e73000000000000000000000000000000000000000000000001", ""},
{"436f757274000000000000000000000000000000000000000000000000000002", ""},
{"53656e6174650000000000000000000000000000000000000000000000000000", ""},
{"436f757274000000000000000000000000000000000000000000000000000000", ""},
{"53656e6174650000000000000000000000000000000000000000000000000001", ""},
{"0000000000000000000000000000000000000000000000000000000000000113", ""},
{"436974697a656e73000000000000000000000000000000000000000000000000", ""},
{"436974697a656e73000000000000000000000000000000000000000000000002", ""},
{"436f757274000000000000000000000000000000000000000000000000000001", ""},
{"0000000000000000000000000000000000000000000000000000000000000111", ""},
{"53656e6174650000000000000000000000000000000000000000000000000002", ""},
}
for _, e := range data {
trie.Delete(string(ethutil.Hex2Bytes(e.k)))
}
fmt.Printf("root after delete %x\n", trie.Root)
trie.NewIterator().Each(func(k string, v *ethutil.Value) {
fmt.Printf("%x %x\n", k, v.Bytes())
})
fmt.Printf("%x\n", trie.Get(string(ethutil.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000001"))))
}

View File

@ -118,7 +118,7 @@ func FormatData(data string) []byte {
// Simple stupid
d := new(big.Int)
if data[0:1] == "\"" && data[len(data)-1:] == "\"" {
return RightPadBytes([]byte(data), 32)
return RightPadBytes([]byte(data[1:len(data)-1]), 32)
} else if len(data) > 1 && data[:2] == "0x" {
d.SetBytes(Hex2Bytes(data[2:]))
} else {
@ -149,3 +149,17 @@ func LeftPadBytes(slice []byte, l int) []byte {
return padded
}
func Address(slice []byte) (addr []byte) {
if len(slice) < 20 {
addr = LeftPadBytes(slice, 20)
} else if len(slice) > 20 {
addr = slice[len(slice)-20:]
} else {
addr = slice
}
addr = CopyBytes(addr)
return
}

View File

@ -14,6 +14,7 @@ type ConfigManager struct {
ExecPath string
Debug bool
Diff bool
DiffType string
Paranoia bool
conf *globalconf.GlobalConf

View File

@ -40,13 +40,9 @@ func (val *Value) Len() int {
//return val.kind.Len()
if data, ok := val.Val.([]interface{}); ok {
return len(data)
} else if data, ok := val.Val.([]byte); ok {
return len(data)
} else if data, ok := val.Val.(string); ok {
return len(data)
}
return 0
return len(val.Bytes())
}
func (val *Value) Raw() interface{} {
@ -118,6 +114,8 @@ func (val *Value) Bytes() []byte {
return []byte{s}
} else if s, ok := val.Val.(string); ok {
return []byte(s)
} else if s, ok := val.Val.(*big.Int); ok {
return s.Bytes()
}
return []byte{}
@ -190,6 +188,19 @@ func (val *Value) Get(idx int) *Value {
return NewValue(nil)
}
func (self *Value) Copy() *Value {
switch val := self.Val.(type) {
case *big.Int:
return NewValue(new(big.Int).Set(val))
case []byte:
return NewValue(CopyBytes(val))
default:
return NewValue(self.Val)
}
return nil
}
func (val *Value) Cmp(o *Value) bool {
return reflect.DeepEqual(val.Val, o.Val)
}

13
peer.go
View File

@ -319,7 +319,7 @@ func (p *Peer) HandleInbound() {
for atomic.LoadInt32(&p.disconnect) == 0 {
// HMM?
time.Sleep(500 * time.Millisecond)
time.Sleep(50 * time.Millisecond)
// Wait for a message from the peer
msgs, err := ethwire.ReadMessages(p.conn)
if err != nil {
@ -328,6 +328,7 @@ func (p *Peer) HandleInbound() {
for _, msg := range msgs {
peerlogger.DebugDetailf("(%v) => %v %v\n", p.conn.RemoteAddr(), msg.Type, msg.Data)
nextMsg:
switch msg.Type {
case ethwire.MsgHandshakeTy:
// Version message
@ -373,6 +374,7 @@ func (p *Peer) HandleInbound() {
p.diverted = false
if !p.ethereum.StateManager().BlockChain().FindCanonicalChainFromMsg(msg, block.PrevHash) {
p.SyncWithPeerToLastKnown()
break nextMsg
}
break
}
@ -385,10 +387,11 @@ func (p *Peer) HandleInbound() {
p.blocksRequested = p.blocksRequested * 2
peerlogger.Infof("No common ancestor found, requesting %d more blocks.\n", p.blocksRequested)
p.catchingUp = false
p.FindCommonParentBlock()
break
break nextMsg
}
p.catchingUp = false
}
for i := msg.Data.Len() - 1; i >= 0; i-- {
@ -410,7 +413,7 @@ func (p *Peer) HandleInbound() {
}
}
if msg.Data.Len() == 0 {
if msg.Data.Len() <= 1 {
// Set catching up to false if
// the peer has nothing left to give
p.catchingUp = false
@ -754,7 +757,7 @@ func (p *Peer) CatchupWithPeer(blockHash []byte) {
if !p.catchingUp {
// Make sure nobody else is catching up when you want to do this
p.catchingUp = true
msg := ethwire.NewMessage(ethwire.MsgGetChainTy, []interface{}{blockHash, uint64(10)})
msg := ethwire.NewMessage(ethwire.MsgGetChainTy, []interface{}{blockHash, uint64(30)})
p.QueueMessage(msg)
peerlogger.DebugDetailf("Requesting blockchain %x... from peer %s\n", p.ethereum.BlockChain().CurrentBlock.Hash()[:4], p.conn.RemoteAddr())