aboutsummaryrefslogtreecommitdiffstats
path: root/ethstate
diff options
context:
space:
mode:
authorobscuren <geffobscura@gmail.com>2014-08-21 21:46:26 +0800
committerobscuren <geffobscura@gmail.com>2014-08-21 21:46:26 +0800
commit0af0f0d890120e007ce42f072e1ee179a62115d3 (patch)
tree5ae9ecafbb729d1636fadfcfa49fd9100959560c /ethstate
parentd761af84c83ae8d9d723e6766abb7950ff59cdf3 (diff)
parentc173e9f4ab463cf3a44d35215bc29d846d6f6b02 (diff)
downloadgo-tangerine-0af0f0d890120e007ce42f072e1ee179a62115d3.tar
go-tangerine-0af0f0d890120e007ce42f072e1ee179a62115d3.tar.gz
go-tangerine-0af0f0d890120e007ce42f072e1ee179a62115d3.tar.bz2
go-tangerine-0af0f0d890120e007ce42f072e1ee179a62115d3.tar.lz
go-tangerine-0af0f0d890120e007ce42f072e1ee179a62115d3.tar.xz
go-tangerine-0af0f0d890120e007ce42f072e1ee179a62115d3.tar.zst
go-tangerine-0af0f0d890120e007ce42f072e1ee179a62115d3.zip
Merge branch 'release/0.6.3'
Diffstat (limited to 'ethstate')
-rw-r--r--ethstate/dump.go47
-rw-r--r--ethstate/manifest.go55
-rw-r--r--ethstate/state.go56
-rw-r--r--ethstate/state_object.go63
-rw-r--r--ethstate/state_test.go5
5 files changed, 137 insertions, 89 deletions
diff --git a/ethstate/dump.go b/ethstate/dump.go
new file mode 100644
index 000000000..be60a05fc
--- /dev/null
+++ b/ethstate/dump.go
@@ -0,0 +1,47 @@
+package ethstate
+
+import (
+ "encoding/json"
+ "fmt"
+
+ "github.com/ethereum/eth-go/ethutil"
+)
+
+type Account struct {
+ Balance string `json:"balance"`
+ Nonce uint64 `json:"nonce"`
+ CodeHash string `json:"codeHash"`
+ Storage map[string]string `json:"storage"`
+}
+
+type World struct {
+ Root string `json:"root"`
+ Accounts map[string]Account `json:"accounts"`
+}
+
+func (self *State) Dump() []byte {
+ world := World{
+ Root: ethutil.Bytes2Hex(self.Trie.Root.([]byte)),
+ Accounts: make(map[string]Account),
+ }
+
+ self.Trie.NewIterator().Each(func(key string, value *ethutil.Value) {
+ stateObject := NewStateObjectFromBytes([]byte(key), value.Bytes())
+
+ account := Account{Balance: stateObject.Balance.String(), Nonce: stateObject.Nonce, CodeHash: ethutil.Bytes2Hex(stateObject.CodeHash)}
+ account.Storage = make(map[string]string)
+
+ stateObject.EachStorage(func(key string, value *ethutil.Value) {
+ value.Decode()
+ account.Storage[ethutil.Bytes2Hex([]byte(key))] = ethutil.Bytes2Hex(value.Bytes())
+ })
+ world.Accounts[ethutil.Bytes2Hex([]byte(key))] = account
+ })
+
+ json, err := json.MarshalIndent(world, "", " ")
+ if err != nil {
+ fmt.Println("dump err", err)
+ }
+
+ return json
+}
diff --git a/ethstate/manifest.go b/ethstate/manifest.go
new file mode 100644
index 000000000..945de22ab
--- /dev/null
+++ b/ethstate/manifest.go
@@ -0,0 +1,55 @@
+package ethstate
+
+import (
+ "fmt"
+ "math/big"
+)
+
+// Object manifest
+//
+// The object manifest is used to keep changes to the state so we can keep track of the changes
+// that occurred during a state transitioning phase.
+type Manifest struct {
+ Messages Messages
+}
+
+func NewManifest() *Manifest {
+ m := &Manifest{}
+ m.Reset()
+
+ return m
+}
+
+func (m *Manifest) Reset() {
+ m.Messages = nil
+}
+
+func (self *Manifest) AddMessage(msg *Message) *Message {
+ self.Messages = append(self.Messages, msg)
+
+ return msg
+}
+
+type Messages []*Message
+type Message struct {
+ To, From []byte
+ Input []byte
+ Output []byte
+ Path int
+ Origin []byte
+ Timestamp int64
+ Coinbase []byte
+ Block []byte
+ Number *big.Int
+ Value *big.Int
+
+ ChangedAddresses [][]byte
+}
+
+func (self *Message) AddStorageChange(addr []byte) {
+ self.ChangedAddresses = append(self.ChangedAddresses, addr)
+}
+
+func (self *Message) String() string {
+ return fmt.Sprintf("Message{to: %x from: %x input: %x output: %x origin: %x coinbase: %x block: %x number: %v timestamp: %d path: %d value: %v", self.To, self.From, self.Input, self.Output, self.Origin, self.Coinbase, self.Block, self.Number, self.Timestamp, self.Path, self.Value)
+}
diff --git a/ethstate/state.go b/ethstate/state.go
index 51b585d4d..cf060e795 100644
--- a/ethstate/state.go
+++ b/ethstate/state.go
@@ -1,11 +1,12 @@
package ethstate
import (
+ "math/big"
+
"github.com/ethereum/eth-go/ethcrypto"
"github.com/ethereum/eth-go/ethlog"
"github.com/ethereum/eth-go/ethtrie"
"github.com/ethereum/eth-go/ethutil"
- "math/big"
)
var statelogger = ethlog.NewLogger("STATE")
@@ -25,7 +26,7 @@ type State struct {
}
// Create a new state from a given trie
-func NewState(trie *ethtrie.Trie) *State {
+func New(trie *ethtrie.Trie) *State {
return &State{Trie: trie, stateObjects: make(map[string]*StateObject), manifest: NewManifest()}
}
@@ -33,7 +34,7 @@ func NewState(trie *ethtrie.Trie) *State {
func (self *State) GetBalance(addr []byte) *big.Int {
stateObject := self.GetStateObject(addr)
if stateObject != nil {
- return stateObject.Amount
+ return stateObject.Balance
}
return ethutil.Big0
@@ -59,8 +60,6 @@ func (self *State) UpdateStateObject(stateObject *StateObject) {
ethutil.Config.Db.Put(ethcrypto.Sha3Bin(stateObject.Code), stateObject.Code)
self.Trie.Update(string(addr), string(stateObject.RlpEncode()))
-
- self.manifest.AddObjectChange(stateObject)
}
// Delete the given state object and delete it from the state trie
@@ -127,7 +126,7 @@ func (s *State) Cmp(other *State) bool {
func (self *State) Copy() *State {
if self.Trie != nil {
- state := NewState(self.Trie.Copy())
+ state := New(self.Trie.Copy())
for k, stateObject := range self.stateObjects {
state.stateObjects[k] = stateObject.Copy()
}
@@ -210,50 +209,13 @@ func (self *State) Update() {
}
}
-// Debug stuff
-func (self *State) CreateOutputForDiff() {
- for _, stateObject := range self.stateObjects {
- stateObject.CreateOutputForDiff()
- }
-}
-
func (self *State) Manifest() *Manifest {
return self.manifest
}
-// Object manifest
-//
-// The object manifest is used to keep changes to the state so we can keep track of the changes
-// that occurred during a state transitioning phase.
-type Manifest struct {
- // XXX These will be handy in the future. Not important for now.
- objectAddresses map[string]bool
- storageAddresses map[string]map[string]bool
-
- ObjectChanges map[string]*StateObject
- StorageChanges map[string]map[string]*big.Int
-}
-
-func NewManifest() *Manifest {
- m := &Manifest{objectAddresses: make(map[string]bool), storageAddresses: make(map[string]map[string]bool)}
- m.Reset()
-
- return m
-}
-
-func (m *Manifest) Reset() {
- m.ObjectChanges = make(map[string]*StateObject)
- m.StorageChanges = make(map[string]map[string]*big.Int)
-}
-
-func (m *Manifest) AddObjectChange(stateObject *StateObject) {
- m.ObjectChanges[string(stateObject.Address())] = stateObject
-}
-
-func (m *Manifest) AddStorageChange(stateObject *StateObject, storageAddr []byte, storage *big.Int) {
- if m.StorageChanges[string(stateObject.Address())] == nil {
- m.StorageChanges[string(stateObject.Address())] = make(map[string]*big.Int)
+// Debug stuff
+func (self *State) CreateOutputForDiff() {
+ for _, stateObject := range self.stateObjects {
+ stateObject.CreateOutputForDiff()
}
-
- m.StorageChanges[string(stateObject.Address())][string(storageAddr)] = storage
}
diff --git a/ethstate/state_object.go b/ethstate/state_object.go
index ab14b8604..67d09edd8 100644
--- a/ethstate/state_object.go
+++ b/ethstate/state_object.go
@@ -2,10 +2,11 @@ package ethstate
import (
"fmt"
+ "math/big"
+
"github.com/ethereum/eth-go/ethcrypto"
"github.com/ethereum/eth-go/ethtrie"
"github.com/ethereum/eth-go/ethutil"
- "math/big"
)
type Code []byte
@@ -30,7 +31,7 @@ type StateObject struct {
// Address of the object
address []byte
// Shared attributes
- Amount *big.Int
+ Balance *big.Int
CodeHash []byte
Nonce uint64
// Contract related attributes
@@ -56,40 +57,22 @@ func (self *StateObject) Reset() {
self.State.Reset()
}
-/*
-// Converts an transaction in to a state object
-func MakeContract(tx *Transaction, state *State) *StateObject {
- // Create contract if there's no recipient
- if tx.IsContract() {
- addr := tx.CreationAddress()
-
- contract := state.NewStateObject(addr)
- contract.initCode = tx.Data
- contract.state = NewState(ethtrie.NewTrie(ethutil.Config.Db, ""))
-
- return contract
- }
-
- return nil
-}
-*/
-
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.Address(addr)
- object := &StateObject{address: address, Amount: new(big.Int), gasPool: new(big.Int)}
- object.State = NewState(ethtrie.NewTrie(ethutil.Config.Db, ""))
+ object := &StateObject{address: address, Balance: new(big.Int), gasPool: new(big.Int)}
+ object.State = New(ethtrie.New(ethutil.Config.Db, ""))
object.storage = make(Storage)
object.gasPool = new(big.Int)
return object
}
-func NewContract(address []byte, Amount *big.Int, root []byte) *StateObject {
+func NewContract(address []byte, balance *big.Int, root []byte) *StateObject {
contract := NewStateObject(address)
- contract.Amount = Amount
- contract.State = NewState(ethtrie.NewTrie(ethutil.Config.Db, string(root)))
+ contract.Balance = balance
+ contract.State = New(ethtrie.New(ethutil.Config.Db, string(root)))
return contract
}
@@ -103,7 +86,7 @@ func NewStateObjectFromBytes(address, data []byte) *StateObject {
func (self *StateObject) MarkForDeletion() {
self.remove = true
- statelogger.DebugDetailf("%x: #%d %v (deletion)\n", self.Address(), self.Nonce, self.Amount)
+ statelogger.DebugDetailf("%x: #%d %v (deletion)\n", self.Address(), self.Nonce, self.Balance)
}
func (c *StateObject) GetAddr(addr []byte) *ethutil.Value {
@@ -190,19 +173,19 @@ 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))
+ c.SetBalance(new(big.Int).Add(c.Balance, amount))
- statelogger.Debugf("%x: #%d %v (+ %v)\n", c.Address(), c.Nonce, c.Amount, amount)
+ statelogger.Debugf("%x: #%d %v (+ %v)\n", c.Address(), c.Nonce, c.Balance, amount)
}
func (c *StateObject) SubAmount(amount *big.Int) {
- c.SetAmount(new(big.Int).Sub(c.Amount, amount))
+ c.SetBalance(new(big.Int).Sub(c.Balance, amount))
- statelogger.Debugf("%x: #%d %v (- %v)\n", c.Address(), c.Nonce, c.Amount, amount)
+ statelogger.Debugf("%x: #%d %v (- %v)\n", c.Address(), c.Nonce, c.Balance, amount)
}
-func (c *StateObject) SetAmount(amount *big.Int) {
- c.Amount = amount
+func (c *StateObject) SetBalance(amount *big.Int) {
+ c.Balance = amount
}
//
@@ -213,8 +196,8 @@ func (c *StateObject) SetAmount(amount *big.Int) {
func (c *StateObject) ReturnGas(gas, price *big.Int) {}
func (c *StateObject) ConvertGas(gas, price *big.Int) error {
total := new(big.Int).Mul(gas, price)
- if total.Cmp(c.Amount) > 0 {
- return fmt.Errorf("insufficient amount: %v, %v", c.Amount, total)
+ if total.Cmp(c.Balance) > 0 {
+ return fmt.Errorf("insufficient amount: %v, %v", c.Balance, total)
}
c.SubAmount(total)
@@ -247,12 +230,12 @@ func (self *StateObject) RefundGas(gas, price *big.Int) {
rGas := new(big.Int).Set(gas)
rGas.Mul(rGas, price)
- self.Amount.Sub(self.Amount, rGas)
+ self.Balance.Sub(self.Balance, rGas)
}
func (self *StateObject) Copy() *StateObject {
stateObject := NewStateObject(self.Address())
- stateObject.Amount.Set(self.Amount)
+ stateObject.Balance.Set(self.Balance)
stateObject.CodeHash = ethutil.CopyBytes(self.CodeHash)
stateObject.Nonce = self.Nonce
if self.State != nil {
@@ -290,7 +273,7 @@ func (c *StateObject) Init() Code {
// Debug stuff
func (self *StateObject) CreateOutputForDiff() {
- fmt.Printf("%x %x %x %x\n", self.Address(), self.State.Root(), self.Amount.Bytes(), self.Nonce)
+ fmt.Printf("%x %x %x %x\n", self.Address(), self.State.Root(), self.Balance.Bytes(), self.Nonce)
self.EachStorage(func(addr string, value *ethutil.Value) {
fmt.Printf("%x %x\n", addr, value.Bytes())
})
@@ -309,15 +292,15 @@ func (c *StateObject) RlpEncode() []byte {
root = ""
}
- return ethutil.Encode([]interface{}{c.Nonce, c.Amount, root, ethcrypto.Sha3Bin(c.Code)})
+ return ethutil.Encode([]interface{}{c.Nonce, c.Balance, root, ethcrypto.Sha3Bin(c.Code)})
}
func (c *StateObject) RlpDecode(data []byte) {
decoder := ethutil.NewValueFromBytes(data)
c.Nonce = decoder.Get(0).Uint()
- c.Amount = decoder.Get(1).BigInt()
- c.State = NewState(ethtrie.NewTrie(ethutil.Config.Db, decoder.Get(2).Interface()))
+ c.Balance = decoder.Get(1).BigInt()
+ c.State = New(ethtrie.New(ethutil.Config.Db, decoder.Get(2).Interface()))
c.storage = make(map[string]*ethutil.Value)
c.gasPool = new(big.Int)
diff --git a/ethstate/state_test.go b/ethstate/state_test.go
index cd13e80bc..00c9de9d6 100644
--- a/ethstate/state_test.go
+++ b/ethstate/state_test.go
@@ -1,10 +1,11 @@
package ethstate
import (
+ "testing"
+
"github.com/ethereum/eth-go/ethdb"
"github.com/ethereum/eth-go/ethtrie"
"github.com/ethereum/eth-go/ethutil"
- "testing"
)
var ZeroHash256 = make([]byte, 32)
@@ -14,7 +15,7 @@ func TestSnapshot(t *testing.T) {
ethutil.ReadConfig(".ethtest", "/tmp/ethtest", "")
ethutil.Config.Db = db
- state := NewState(ethtrie.NewTrie(db, ""))
+ state := New(ethtrie.New(db, ""))
stateObject := state.GetOrNewStateObject([]byte("aa"))