aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorzelig <viktor.tron@gmail.com>2014-06-23 20:07:43 +0800
committerzelig <viktor.tron@gmail.com>2014-06-23 20:07:43 +0800
commitf58c7ac5a6f5d77649c1c07dce94bf6d5c146c31 (patch)
tree31e286974108e02b29ed5eff0a73646f605998c2
parent63157c798d613f1ca638597515bb89768e2c1aad (diff)
parentd890258af6de8c5ef9701826fb4ee7c353788ad5 (diff)
downloadgo-tangerine-f58c7ac5a6f5d77649c1c07dce94bf6d5c146c31.tar
go-tangerine-f58c7ac5a6f5d77649c1c07dce94bf6d5c146c31.tar.gz
go-tangerine-f58c7ac5a6f5d77649c1c07dce94bf6d5c146c31.tar.bz2
go-tangerine-f58c7ac5a6f5d77649c1c07dce94bf6d5c146c31.tar.lz
go-tangerine-f58c7ac5a6f5d77649c1c07dce94bf6d5c146c31.tar.xz
go-tangerine-f58c7ac5a6f5d77649c1c07dce94bf6d5c146c31.tar.zst
go-tangerine-f58c7ac5a6f5d77649c1c07dce94bf6d5c146c31.zip
merge upstream
-rw-r--r--ethchain/state_manager.go53
-rw-r--r--ethchain/state_object.go9
-rw-r--r--ethchain/transaction.go12
-rw-r--r--ethchain/vm.go34
-rw-r--r--ethereum.go18
-rw-r--r--ethpub/types.go8
-rw-r--r--ethutil/script.go32
-rw-r--r--peer.go7
8 files changed, 115 insertions, 58 deletions
diff --git a/ethchain/state_manager.go b/ethchain/state_manager.go
index 20e0a13a2..e5941b165 100644
--- a/ethchain/state_manager.go
+++ b/ethchain/state_manager.go
@@ -145,45 +145,31 @@ done:
return receipts, handled, unhandled, err
}
-func (sm *StateManager) Process(block *Block, dontReact bool) error {
- if !sm.bc.HasBlock(block.PrevHash) {
- return ParentError(block.PrevHash)
- }
-
- parent := sm.bc.GetBlock(block.PrevHash)
-
- return sm.ProcessBlock(parent.State(), parent, block, dontReact)
-
-}
-
-// Block processing and validating with a given (temporarily) state
-func (sm *StateManager) ProcessBlock(state *State, parent, block *Block, dontReact bool) (err error) {
+func (sm *StateManager) Process(block *Block, dontReact bool) (err error) {
// Processing a blocks may never happen simultaneously
sm.mutex.Lock()
defer sm.mutex.Unlock()
- hash := block.Hash()
- if sm.bc.HasBlock(hash) {
+ if sm.bc.HasBlock(block.Hash()) {
return nil
}
+ if !sm.bc.HasBlock(block.PrevHash) {
+ return ParentError(block.PrevHash)
+ }
+
+ var (
+ parent = sm.bc.GetBlock(block.PrevHash)
+ state = parent.State()
+ )
+
// Defer the Undo on the Trie. If the block processing happened
// we don't want to undo but since undo only happens on dirty
// nodes this won't happen because Commit would have been called
// before that.
defer state.Reset()
- // Check if we have the parent hash, if it isn't known we discard it
- // Reasons might be catching up or simply an invalid block
- if !sm.bc.HasBlock(block.PrevHash) && sm.bc.CurrentBlock != nil {
- return ParentError(block.PrevHash)
- }
-
- coinbase := state.GetOrNewStateObject(block.Coinbase)
- coinbase.SetGasPool(block.CalcGasLimit(parent))
-
- // Process the transactions on to current block
- receipts, _, _, _ := sm.ProcessTransactions(coinbase, state, block, parent, block.Transactions())
+ receipts, err := sm.ApplyDiff(state, parent, block)
defer func() {
if err != nil {
if len(receipts) == len(block.Receipts()) {
@@ -196,6 +182,10 @@ func (sm *StateManager) ProcessBlock(state *State, parent, block *Block, dontRea
}
}()
+ if err != nil {
+ return err
+ }
+
// Block validation
if err = sm.ValidateBlock(block); err != nil {
statelogger.Errorln("Error validating block:", err)
@@ -239,6 +229,17 @@ func (sm *StateManager) ProcessBlock(state *State, parent, block *Block, dontRea
return nil
}
+
+func (sm *StateManager) ApplyDiff(state *State, parent, block *Block) (receipts Receipts, err error) {
+ coinbase := state.GetOrNewStateObject(block.Coinbase)
+ coinbase.SetGasPool(block.CalcGasLimit(parent))
+
+ // Process the transactions on to current block
+ receipts, _, _, _ = sm.ProcessTransactions(coinbase, state, block, parent, block.Transactions())
+
+ return receipts, nil
+}
+
func (sm *StateManager) CalculateTD(block *Block) bool {
uncleDiff := new(big.Int)
for _, uncle := range block.Uncles {
diff --git a/ethchain/state_object.go b/ethchain/state_object.go
index f53f47d7e..7d7352af4 100644
--- a/ethchain/state_object.go
+++ b/ethchain/state_object.go
@@ -90,7 +90,14 @@ func (c *StateObject) SetAddr(addr []byte, value interface{}) {
func (c *StateObject) SetStorage(num *big.Int, val *ethutil.Value) {
addr := ethutil.BigToBytes(num, 256)
- //fmt.Printf("sstore %x => %v\n", addr, val)
+
+ // FIXME This should be handled in the Trie it self
+ if val.BigInt().Cmp(ethutil.Big0) == 0 {
+ c.state.trie.Delete(string(addr))
+
+ return
+ }
+
c.SetAddr(addr, val)
}
diff --git a/ethchain/transaction.go b/ethchain/transaction.go
index 34ab357a1..2ab681030 100644
--- a/ethchain/transaction.go
+++ b/ethchain/transaction.go
@@ -89,11 +89,12 @@ func (tx *Transaction) Signature(key []byte) []byte {
func (tx *Transaction) PublicKey() []byte {
hash := tx.Hash()
- // If we don't make a copy we will overwrite the existing underlying array
- dst := make([]byte, len(tx.r))
- copy(dst, tx.r)
+ r := make([]byte, 32-len(tx.r))
+ s := make([]byte, 32-len(tx.s))
+ r = append(r, ethutil.CopyBytes(tx.r)...)
+ s = append(s, ethutil.CopyBytes(tx.s)...)
- sig := append(dst, tx.s...)
+ sig := append(r, s...)
sig = append(sig, tx.v-27)
pubkey, _ := secp256k1.RecoverPubkey(hash, sig)
@@ -127,6 +128,8 @@ func (tx *Transaction) Sign(privk []byte) error {
func (tx *Transaction) RlpData() interface{} {
data := []interface{}{tx.Nonce, tx.GasPrice, tx.Gas, tx.Recipient, tx.Value, tx.Data}
+ // TODO Remove prefixing zero's
+
return append(data, tx.v, tx.r, tx.s)
}
@@ -150,6 +153,7 @@ func (tx *Transaction) RlpValueDecode(decoder *ethutil.Value) {
tx.Value = decoder.Get(4).BigInt()
tx.Data = decoder.Get(5).Bytes()
tx.v = byte(decoder.Get(6).Uint())
+
tx.r = decoder.Get(7).Bytes()
tx.s = decoder.Get(8).Bytes()
diff --git a/ethchain/vm.go b/ethchain/vm.go
index 75bcfd782..3a999f0a4 100644
--- a/ethchain/vm.go
+++ b/ethchain/vm.go
@@ -328,21 +328,21 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro
stack.Push(base)
case LT:
require(2)
- y, x := stack.Popn()
- vm.Printf(" %v < %v", x, y)
+ x, y := stack.Popn()
+ vm.Printf(" %v < %v", y, x)
// x < y
- if x.Cmp(y) < 0 {
+ if y.Cmp(x) < 0 {
stack.Push(ethutil.BigTrue)
} else {
stack.Push(ethutil.BigFalse)
}
case GT:
require(2)
- y, x := stack.Popn()
- vm.Printf(" %v > %v", x, y)
+ x, y := stack.Popn()
+ vm.Printf(" %v > %v", y, x)
// x > y
- if x.Cmp(y) > 0 {
+ if y.Cmp(x) > 0 {
stack.Push(ethutil.BigTrue)
} else {
stack.Push(ethutil.BigFalse)
@@ -361,10 +361,10 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro
case NOT:
require(1)
x := stack.Pop()
- if x.Cmp(ethutil.BigFalse) == 0 {
- stack.Push(ethutil.BigTrue)
- } else {
+ if x.Cmp(ethutil.BigFalse) > 0 {
stack.Push(ethutil.BigFalse)
+ } else {
+ stack.Push(ethutil.BigTrue)
}
// 0x10 range
@@ -523,7 +523,10 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro
case MLOAD:
require(1)
offset := stack.Pop()
- stack.Push(ethutil.BigD(mem.Get(offset.Int64(), 32)))
+ val := ethutil.BigD(mem.Get(offset.Int64(), 32))
+ stack.Push(val)
+
+ vm.Printf(" => 0x%x", val.Bytes())
case MSTORE: // Store the value at stack top-1 in to memory at location stack top
require(2)
// Pop value of the stack
@@ -542,17 +545,14 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro
require(1)
loc := stack.Pop()
val := closure.GetMem(loc)
+
stack.Push(val.BigInt())
- vm.Printf(" {} 0x%x", val)
+ vm.Printf(" {0x%x} 0x%x", loc.Bytes(), val.Bytes())
case SSTORE:
require(2)
val, loc := stack.Popn()
-
- // FIXME This should be handled in the Trie it self
- if val.Cmp(big.NewInt(0)) != 0 {
- closure.SetStorage(loc, ethutil.NewValue(val))
- }
+ closure.SetStorage(loc, ethutil.NewValue(val))
// Add the change to manifest
vm.state.manifest.AddStorageChange(closure.Object(), loc.Bytes(), val)
@@ -691,7 +691,7 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro
fallthrough
case STOP: // Stop the closure
- vm.Printf(" (g) %v", closure.Gas).Endl()
+ vm.Endl()
return closure.Return(nil), nil
default:
diff --git a/ethereum.go b/ethereum.go
index 1de671712..0dde28e51 100644
--- a/ethereum.go
+++ b/ethereum.go
@@ -115,6 +115,24 @@ func New(caps Caps, usePnp bool) (*Ethereum, error) {
return ethereum, nil
}
+// Replay block
+func (self *Ethereum) BlockDo(hash []byte) error {
+ block := self.blockChain.GetBlock(hash)
+ if block == nil {
+ return fmt.Errorf("unknown block %x", hash)
+ }
+
+ parent := self.blockChain.GetBlock(block.PrevHash)
+
+ _, err := self.stateManager.ApplyDiff(parent.State(), parent, block)
+ if err != nil {
+ return err
+ }
+
+ return nil
+
+}
+
func (s *Ethereum) Reactor() *ethutil.ReactorEngine {
return s.reactor
}
diff --git a/ethpub/types.go b/ethpub/types.go
index 31b92f6ed..352598148 100644
--- a/ethpub/types.go
+++ b/ethpub/types.go
@@ -244,6 +244,14 @@ func (c *PStateObject) Script() string {
return ""
}
+func (c *PStateObject) HexScript() string {
+ if c.object != nil {
+ return ethutil.Hex(c.object.Script())
+ }
+
+ return ""
+}
+
type PStorageState struct {
StateAddress string
Address string
diff --git a/ethutil/script.go b/ethutil/script.go
index 94e401406..c8b1da51c 100644
--- a/ethutil/script.go
+++ b/ethutil/script.go
@@ -3,23 +3,35 @@ package ethutil
import (
"fmt"
"github.com/obscuren/mutan"
+ "github.com/obscuren/serpent-go"
"strings"
)
// General compile function
-func Compile(script string) ([]byte, error) {
- byteCode, errors := mutan.Compile(strings.NewReader(script), false)
- if len(errors) > 0 {
- var errs string
- for _, er := range errors {
- if er != nil {
- errs += er.Error()
+func Compile(script string) (ret []byte, err error) {
+ c := strings.Split(script, "\n")[0]
+
+ if c == "#!serpent" {
+ byteCode, err := serpent.Compile(script)
+ if err != nil {
+ return nil, err
+ }
+
+ return byteCode, nil
+ } else {
+ byteCode, errors := mutan.Compile(strings.NewReader(script), false)
+ if len(errors) > 0 {
+ var errs string
+ for _, er := range errors {
+ if er != nil {
+ errs += er.Error()
+ }
}
+ return nil, fmt.Errorf("%v", errs)
}
- return nil, fmt.Errorf("%v", errs)
- }
- return byteCode, nil
+ return byteCode, nil
+ }
}
func CompileScript(script string) ([]byte, []byte, error) {
diff --git a/peer.go b/peer.go
index fd8a33d65..18d1da455 100644
--- a/peer.go
+++ b/peer.go
@@ -141,6 +141,8 @@ type Peer struct {
// We use this to give some kind of pingtime to a node, not very accurate, could be improved.
pingTime time.Duration
pingStartTime time.Time
+
+ lastRequestedBlock *ethchain.Block
}
func NewPeer(conn net.Conn, ethereum *Ethereum, inbound bool) *Peer {
@@ -354,6 +356,11 @@ func (p *Peer) HandleInbound() {
// We requested blocks and now we need to make sure we have a common ancestor somewhere in these blocks so we can find
// common ground to start syncing from
lastBlock = ethchain.NewBlockFromRlpValue(msg.Data.Get(msg.Data.Len() - 1))
+ if p.lastRequestedBlock != nil && bytes.Compare(lastBlock.Hash(), p.lastRequestedBlock.Hash()) == 0 {
+ p.catchingUp = false
+ continue
+ }
+ p.lastRequestedBlock = lastBlock
peerlogger.Infof("Last block: %x. Checking if we have it locally.\n", lastBlock.Hash())
for i := msg.Data.Len() - 1; i >= 0; i-- {
block = ethchain.NewBlockFromRlpValue(msg.Data.Get(i))