Merge branch 'release/poc5-rc9'

This commit is contained in:
obscuren 2014-05-26 00:42:07 +02:00
commit b1463b2dc2
23 changed files with 438 additions and 210 deletions

View File

@ -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 5.0 RC8". For build instructions see the [Wiki](https://github.com/ethereum/go-ethereum/wiki/Building-Ethereum(Go)). of Concept 5.0 RC9". 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.

View File

@ -1,6 +1,7 @@
package ethchain package ethchain
import ( import (
"bytes"
"fmt" "fmt"
"github.com/ethereum/eth-go/ethutil" "github.com/ethereum/eth-go/ethutil"
"math/big" "math/big"
@ -55,6 +56,7 @@ type Block struct {
Nonce []byte Nonce []byte
// List of transactions and/or contracts // List of transactions and/or contracts
transactions []*Transaction transactions []*Transaction
receipts []*Receipt
TxSha []byte TxSha []byte
} }
@ -84,12 +86,9 @@ func CreateBlock(root interface{},
base []byte, base []byte,
Difficulty *big.Int, Difficulty *big.Int,
Nonce []byte, Nonce []byte,
extra string, extra string) *Block {
txes []*Transaction) *Block {
block := &Block{ block := &Block{
// Slice of transactions to include in this block
transactions: txes,
PrevHash: prevHash, PrevHash: prevHash,
Coinbase: base, Coinbase: base,
Difficulty: Difficulty, Difficulty: Difficulty,
@ -101,7 +100,6 @@ func CreateBlock(root interface{},
MinGasPrice: new(big.Int), MinGasPrice: new(big.Int),
GasLimit: new(big.Int), GasLimit: new(big.Int),
} }
block.SetTransactions(txes)
block.SetUncles([]*Block{}) block.SetUncles([]*Block{})
block.state = NewState(ethutil.NewTrie(ethutil.Config.Db, root)) block.state = NewState(ethutil.NewTrie(ethutil.Config.Db, root))
@ -115,7 +113,10 @@ func (block *Block) Hash() []byte {
} }
func (block *Block) HashNoNonce() []byte { func (block *Block) HashNoNonce() []byte {
return ethutil.Sha3Bin(ethutil.Encode([]interface{}{block.PrevHash, block.UncleSha, block.Coinbase, block.state.trie.Root, block.TxSha, block.Difficulty, block.Time, block.Extra})) return ethutil.Sha3Bin(ethutil.Encode([]interface{}{block.PrevHash,
block.UncleSha, block.Coinbase, block.state.trie.Root,
block.TxSha, block.Difficulty, block.Number, block.MinGasPrice,
block.GasLimit, block.GasUsed, block.Time, block.Extra}))
} }
func (block *Block) State() *State { func (block *Block) State() *State {
@ -161,6 +162,16 @@ func (block *Block) BlockInfo() BlockInfo {
return bi return bi
} }
func (self *Block) GetTransaction(hash []byte) *Transaction {
for _, receipt := range self.receipts {
if bytes.Compare(receipt.Tx.Hash(), hash) == 0 {
return receipt.Tx
}
}
return nil
}
// Sync the block's state and contract respectively // Sync the block's state and contract respectively
func (block *Block) Sync() { func (block *Block) Sync() {
block.state.Sync() block.state.Sync()
@ -172,15 +183,15 @@ func (block *Block) Undo() {
} }
/////// Block Encoding /////// Block Encoding
func (block *Block) rlpTxs() interface{} { func (block *Block) rlpReceipts() interface{} {
// Marshal the transactions of this block // Marshal the transactions of this block
encTx := make([]interface{}, len(block.transactions)) encR := make([]interface{}, len(block.receipts))
for i, tx := range block.transactions { for i, r := range block.receipts {
// Cast it to a string (safe) // Cast it to a string (safe)
encTx[i] = tx.RlpData() encR[i] = r.RlpData()
} }
return encTx return encR
} }
func (block *Block) rlpUncles() interface{} { func (block *Block) rlpUncles() interface{} {
@ -201,7 +212,12 @@ func (block *Block) SetUncles(uncles []*Block) {
block.UncleSha = ethutil.Sha3Bin(ethutil.Encode(block.rlpUncles())) block.UncleSha = ethutil.Sha3Bin(ethutil.Encode(block.rlpUncles()))
} }
func (block *Block) SetTransactions(txs []*Transaction) { func (self *Block) SetReceipts(receipts []*Receipt, txs []*Transaction) {
self.receipts = receipts
self.setTransactions(txs)
}
func (block *Block) setTransactions(txs []*Transaction) {
block.transactions = txs block.transactions = txs
trie := ethutil.NewTrie(ethutil.Config.Db, "") trie := ethutil.NewTrie(ethutil.Config.Db, "")
@ -221,7 +237,7 @@ func (block *Block) SetTransactions(txs []*Transaction) {
} }
func (block *Block) Value() *ethutil.Value { func (block *Block) Value() *ethutil.Value {
return ethutil.NewValue([]interface{}{block.header(), block.rlpTxs(), block.rlpUncles()}) return ethutil.NewValue([]interface{}{block.header(), block.rlpReceipts(), block.rlpUncles()})
} }
func (block *Block) RlpEncode() []byte { func (block *Block) RlpEncode() []byte {
@ -245,6 +261,7 @@ func (block *Block) RlpValueDecode(decoder *ethutil.Value) {
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()
//fmt.Printf("#%v : %x\n", block.Number, block.Coinbase)
block.MinGasPrice = header.Get(7).BigInt() block.MinGasPrice = header.Get(7).BigInt()
block.GasLimit = header.Get(8).BigInt() block.GasLimit = header.Get(8).BigInt()
block.GasUsed = header.Get(9).BigInt() block.GasUsed = header.Get(9).BigInt()
@ -255,12 +272,13 @@ func (block *Block) RlpValueDecode(decoder *ethutil.Value) {
// Tx list might be empty if this is an uncle. Uncles only have their // Tx list might be empty if this is an uncle. Uncles only have their
// header set. // header set.
if decoder.Get(1).IsNil() == false { // Yes explicitness if decoder.Get(1).IsNil() == false { // Yes explicitness
txes := decoder.Get(1) receipts := decoder.Get(1)
block.transactions = make([]*Transaction, txes.Len()) block.transactions = make([]*Transaction, receipts.Len())
for i := 0; i < txes.Len(); i++ { block.receipts = make([]*Receipt, receipts.Len())
tx := NewTransactionFromValue(txes.Get(i)) for i := 0; i < receipts.Len(); i++ {
receipt := NewRecieptFromValue(receipts.Get(i))
block.transactions[i] = tx block.transactions[i] = receipt.Tx
block.receipts[i] = receipt
} }
} }
@ -299,6 +317,10 @@ func (block *Block) GetRoot() interface{} {
return block.state.trie.Root return block.state.trie.Root
} }
func (self *Block) Receipts() []*Receipt {
return self.receipts
}
func (block *Block) header() []interface{} { func (block *Block) header() []interface{} {
return []interface{}{ return []interface{}{
// Sha of the previous block // Sha of the previous block
@ -346,6 +368,7 @@ func (block *Block) String() string {
Time: %v Time: %v
Extra: %v Extra: %v
Nonce: %x Nonce: %x
NumTx: %v
`, `,
block.Hash(), block.Hash(),
block.PrevHash, block.PrevHash,
@ -360,5 +383,7 @@ func (block *Block) String() string {
block.GasUsed, block.GasUsed,
block.Time, block.Time,
block.Extra, block.Extra,
block.Nonce) block.Nonce,
len(block.transactions),
)
} }

View File

@ -36,7 +36,7 @@ func (bc *BlockChain) Genesis() *Block {
return bc.genesisBlock return bc.genesisBlock
} }
func (bc *BlockChain) NewBlock(coinbase []byte, txs []*Transaction) *Block { func (bc *BlockChain) NewBlock(coinbase []byte) *Block {
var root interface{} var root interface{}
var lastBlockTime int64 var lastBlockTime int64
hash := ZeroHash256 hash := ZeroHash256
@ -53,8 +53,7 @@ func (bc *BlockChain) NewBlock(coinbase []byte, txs []*Transaction) *Block {
coinbase, coinbase,
ethutil.BigPow(2, 32), ethutil.BigPow(2, 32),
nil, nil,
"", "")
txs)
if bc.CurrentBlock != nil { if bc.CurrentBlock != nil {
var mul *big.Int var mul *big.Int
@ -272,16 +271,18 @@ func (bc *BlockChain) GetChain(hash []byte, amount int) []*Block {
func AddTestNetFunds(block *Block) { func AddTestNetFunds(block *Block) {
for _, addr := range []string{ for _, addr := range []string{
"8a40bfaa73256b60764c1bf40675a99083efb075", // Gavin "8a40bfaa73256b60764c1bf40675a99083efb075",
"e6716f9544a56c530d868e4bfbacb172315bdead", // Jeffrey "e4157b34ea9615cfbde6b4fda419828124b70c78",
"1e12515ce3e0f817a4ddef9ca55788a1d66bd2df", // Vit "1e12515ce3e0f817a4ddef9ca55788a1d66bd2df",
"1a26338f0d905e295fccb71fa9ea849ffa12aaf4", // Alex "6c386a4b26f73c802f34673f7248bb118f97424a",
"2ef47100e0787b915105fd5e3f4ff6752079d5cb", // Maran "cd2a3d9f938e13cd947ec05abc7fe734df8dd826",
"cd2a3d9f938e13cd947ec05abc7fe734df8dd826", // Roman "2ef47100e0787b915105fd5e3f4ff6752079d5cb",
"e6716f9544a56c530d868e4bfbacb172315bdead",
"1a26338f0d905e295fccb71fa9ea849ffa12aaf4",
} { } {
codedAddr := ethutil.FromHex(addr) codedAddr := ethutil.FromHex(addr)
account := block.state.GetAccount(codedAddr) account := block.state.GetAccount(codedAddr)
account.Amount = ethutil.BigPow(2, 200) account.Amount = ethutil.Big("1606938044258990275541962092341162602522202993782792835301376") //ethutil.BigPow(2, 200)
block.state.UpdateStateObject(account) block.state.UpdateStateObject(account)
} }
log.Printf("%x\n", block.RlpEncode()) log.Printf("%x\n", block.RlpEncode())

View File

@ -50,7 +50,7 @@ func (tm *TestManager) Broadcast(msgType ethwire.MsgType, data []interface{}) {
} }
func NewTestManager() *TestManager { func NewTestManager() *TestManager {
ethutil.ReadConfig(".ethtest", ethutil.LogStd) ethutil.ReadConfig(".ethtest", ethutil.LogStd, "")
db, err := ethdb.NewMemDatabase() db, err := ethdb.NewMemDatabase()
if err != nil { if err != nil {
@ -74,7 +74,7 @@ func NewTestManager() *TestManager {
func (tm *TestManager) AddFakeBlock(blk []byte) error { func (tm *TestManager) AddFakeBlock(blk []byte) error {
block := NewBlockFromBytes(blk) block := NewBlockFromBytes(blk)
tm.Blocks = append(tm.Blocks, block) tm.Blocks = append(tm.Blocks, block)
err := tm.StateManager().ProcessBlock(tm.StateManager().CurrentState(), block, false) err := tm.StateManager().Process(block, false)
return err return err
} }
func (tm *TestManager) CreateChain1() error { func (tm *TestManager) CreateChain1() error {

View File

@ -23,7 +23,7 @@ var GenesisHeader = []interface{}{
// Root state // Root state
"", "",
// tx sha // tx sha
ZeroHash256, "",
// Difficulty // Difficulty
ethutil.BigPow(2, 22), ethutil.BigPow(2, 22),
// Number // Number

View File

@ -99,7 +99,21 @@ func (s *State) Cmp(other *State) bool {
} }
func (s *State) Copy() *State { func (s *State) Copy() *State {
return NewState(s.trie.Copy()) state := NewState(s.trie.Copy())
for k, subState := range s.states {
state.states[k] = subState.Copy()
}
return state
}
func (s *State) Snapshot() *State {
return s.Copy()
}
func (s *State) Revert(snapshot *State) {
s.trie = snapshot.trie
s.states = snapshot.states
} }
func (s *State) Put(key, object []byte) { func (s *State) Put(key, object []byte) {

View File

@ -84,7 +84,7 @@ func (sm *StateManager) BlockChain() *BlockChain {
return sm.bc return sm.bc
} }
func (sm *StateManager) MakeContract(state *State, tx *Transaction) *StateObject { func (sm *StateManager) MakeStateObject(state *State, tx *Transaction) *StateObject {
contract := MakeContract(tx, state) contract := MakeContract(tx, state)
if contract != nil { if contract != nil {
state.states[string(tx.CreationAddress())] = contract.state state.states[string(tx.CreationAddress())] = contract.state
@ -97,40 +97,74 @@ func (sm *StateManager) MakeContract(state *State, tx *Transaction) *StateObject
// Apply transactions uses the transaction passed to it and applies them onto // Apply transactions uses the transaction passed to it and applies them onto
// the current processing state. // the current processing state.
func (sm *StateManager) ApplyTransactions(state *State, block *Block, txs []*Transaction) { func (sm *StateManager) ApplyTransactions(state *State, block *Block, txs []*Transaction) ([]*Receipt, []*Transaction) {
// Process each transaction/contract // Process each transaction/contract
var receipts []*Receipt
var validTxs []*Transaction
totalUsedGas := big.NewInt(0)
for _, tx := range txs { for _, tx := range txs {
sm.ApplyTransaction(state, block, tx) usedGas, err := sm.ApplyTransaction(state, block, tx)
} if err != nil {
ethutil.Config.Log.Infoln(err)
continue
} }
func (sm *StateManager) ApplyTransaction(state *State, block *Block, tx *Transaction) error { accumelative := new(big.Int).Set(totalUsedGas.Add(totalUsedGas, usedGas))
// If there's no recipient, it's a contract receipt := &Receipt{tx, ethutil.CopyBytes(state.Root().([]byte)), accumelative}
// Check if this is a contract creation traction and if so
// create a contract of this tx. receipts = append(receipts, receipt)
if tx.IsContract() { validTxs = append(validTxs, tx)
err := sm.Ethereum.TxPool().ProcessTransaction(tx, block, false) }
return receipts, txs
}
func (sm *StateManager) ApplyTransaction(state *State, block *Block, tx *Transaction) (*big.Int, error) {
/*
Applies transactions to the given state and creates new
state objects where needed.
If said objects needs to be created
run the initialization script provided by the transaction and
assume there's a return value. The return value will be set to
the script section of the state object.
*/
totalGasUsed := big.NewInt(0)
// Apply the transaction to the current state
err := sm.Ethereum.TxPool().ProcessTransaction(tx, state, false)
if tx.CreatesContract() {
if err == nil { if err == nil {
contract := sm.MakeContract(state, tx) // Create a new state object and the transaction
// as it's data provider.
contract := sm.MakeStateObject(state, tx)
if contract != nil { if contract != nil {
sm.EvalScript(state, contract.Init(), contract, tx, block) // Evaluate the initialization script
// and use the return value as the
// script section for the state object.
script, err := sm.EvalScript(state, contract.Init(), contract, tx, block)
if err != nil {
return nil, fmt.Errorf("[STATE] Error during init script run %v", err)
}
contract.script = script
state.UpdateStateObject(contract)
} else { } else {
return fmt.Errorf("[STATE] Unable to create contract") return nil, fmt.Errorf("[STATE] Unable to create contract")
} }
} else { } else {
return fmt.Errorf("[STATE] contract create:", err) return nil, fmt.Errorf("[STATE] contract creation tx:", err)
} }
} else { } else {
err := sm.Ethereum.TxPool().ProcessTransaction(tx, block, false) // Find the state object at the "recipient" address. If
contract := state.GetStateObject(tx.Recipient) // there's an object attempt to run the script.
if err == nil && contract != nil && len(contract.Script()) > 0 { stateObject := state.GetStateObject(tx.Recipient)
sm.EvalScript(state, contract.Script(), contract, tx, block) if err == nil && stateObject != nil && len(stateObject.Script()) > 0 {
sm.EvalScript(state, stateObject.Script(), stateObject, tx, block)
} else if err != nil { } else if err != nil {
return fmt.Errorf("[STATE] process:", err) return nil, fmt.Errorf("[STATE] process:", err)
} }
} }
return nil return totalGasUsed, nil
} }
func (sm *StateManager) Process(block *Block, dontReact bool) error { func (sm *StateManager) Process(block *Block, dontReact bool) error {
@ -276,6 +310,14 @@ func CalculateBlockReward(block *Block, uncleLength int) *big.Int {
for i := 0; i < uncleLength; i++ { for i := 0; i < uncleLength; i++ {
base.Add(base, UncleInclusionReward) base.Add(base, UncleInclusionReward)
} }
lastCumulGasUsed := big.NewInt(0)
for _, r := range block.Receipts() {
usedGas := new(big.Int).Sub(r.CumulativeGasUsed, lastCumulGasUsed)
usedGas.Add(usedGas, r.Tx.GasPrice)
base.Add(base, usedGas)
}
return base.Add(base, BlockReward) return base.Add(base, BlockReward)
} }
@ -307,10 +349,10 @@ func (sm *StateManager) Stop() {
sm.bc.Stop() sm.bc.Stop()
} }
func (sm *StateManager) EvalScript(state *State, script []byte, object *StateObject, tx *Transaction, block *Block) { func (sm *StateManager) EvalScript(state *State, script []byte, object *StateObject, tx *Transaction, block *Block) (ret []byte, err error) {
account := state.GetAccount(tx.Sender()) account := state.GetAccount(tx.Sender())
err := account.ConvertGas(tx.Gas, tx.GasPrice) err = account.ConvertGas(tx.Gas, tx.GasPrice)
if err != nil { if err != nil {
ethutil.Config.Log.Debugln(err) ethutil.Config.Log.Debugln(err)
return return
@ -327,11 +369,13 @@ func (sm *StateManager) EvalScript(state *State, script []byte, object *StateObj
Value: tx.Value, Value: tx.Value,
//Price: tx.GasPrice, //Price: tx.GasPrice,
}) })
closure.Call(vm, tx.Data, nil) ret, err = closure.Call(vm, tx.Data, nil)
// Update the account (refunds) // Update the account (refunds)
state.UpdateStateObject(account) state.UpdateStateObject(account)
state.UpdateStateObject(object) state.UpdateStateObject(object)
return
} }
func (sm *StateManager) notifyChanges(state *State) { func (sm *StateManager) notifyChanges(state *State) {

View File

@ -28,8 +28,7 @@ func MakeContract(tx *Transaction, state *State) *StateObject {
value := tx.Value value := tx.Value
contract := NewContract(addr, value, ZeroHash256) contract := NewContract(addr, value, ZeroHash256)
contract.script = tx.Data contract.initScript = tx.Data
contract.initScript = tx.Init
state.UpdateStateObject(contract) state.UpdateStateObject(contract)
@ -82,12 +81,17 @@ func (c *StateObject) SetStorage(num *big.Int, val *ethutil.Value) {
c.SetAddr(addr, val) c.SetAddr(addr, val)
} }
func (c *StateObject) GetMem(num *big.Int) *ethutil.Value { func (c *StateObject) GetStorage(num *big.Int) *ethutil.Value {
nb := ethutil.BigToBytes(num, 256) nb := ethutil.BigToBytes(num, 256)
return c.Addr(nb) return c.Addr(nb)
} }
/* DEPRECATED */
func (c *StateObject) GetMem(num *big.Int) *ethutil.Value {
return c.GetStorage(num)
}
func (c *StateObject) GetInstr(pc *big.Int) *ethutil.Value { func (c *StateObject) GetInstr(pc *big.Int) *ethutil.Value {
if int64(len(c.script)-1) < pc.Int64() { if int64(len(c.script)-1) < pc.Int64() {
return ethutil.NewValue(0) return ethutil.NewValue(0)
@ -146,7 +150,7 @@ func (c *StateObject) RlpEncode() []byte {
if c.state != nil { if c.state != nil {
root = c.state.trie.Root root = c.state.trie.Root
} else { } else {
root = ZeroHash256 root = ""
} }
return ethutil.Encode([]interface{}{c.Amount, c.Nonce, root, ethutil.Sha3Bin(c.script)}) return ethutil.Encode([]interface{}{c.Amount, c.Nonce, root, ethutil.Sha3Bin(c.script)})

View File

@ -9,7 +9,7 @@ import (
) )
func TestSync(t *testing.T) { func TestSync(t *testing.T) {
ethutil.ReadConfig("", ethutil.LogStd) ethutil.ReadConfig("", ethutil.LogStd, "")
db, _ := ethdb.NewMemDatabase() db, _ := ethdb.NewMemDatabase()
state := NewState(ethutil.NewTrie(db, "")) state := NewState(ethutil.NewTrie(db, ""))
@ -28,7 +28,7 @@ func TestSync(t *testing.T) {
} }
func TestObjectGet(t *testing.T) { func TestObjectGet(t *testing.T) {
ethutil.ReadConfig("", ethutil.LogStd) ethutil.ReadConfig("", ethutil.LogStd, "")
db, _ := ethdb.NewMemDatabase() db, _ := ethdb.NewMemDatabase()
ethutil.Config.Db = db ethutil.Config.Db = db

31
ethchain/state_test.go Normal file
View File

@ -0,0 +1,31 @@
package ethchain
import (
"fmt"
"github.com/ethereum/eth-go/ethdb"
"github.com/ethereum/eth-go/ethutil"
"testing"
)
func TestSnapshot(t *testing.T) {
ethutil.ReadConfig("", ethutil.LogStd, "")
db, _ := ethdb.NewMemDatabase()
state := NewState(ethutil.NewTrie(db, ""))
stateObject := NewContract([]byte("aa"), ethutil.Big1, ZeroHash256)
state.UpdateStateObject(stateObject)
stateObject.SetStorage(ethutil.Big("0"), ethutil.NewValue(42))
snapshot := state.Snapshot()
stateObject = state.GetStateObject([]byte("aa"))
stateObject.SetStorage(ethutil.Big("0"), ethutil.NewValue(43))
state.Revert(snapshot)
stateObject = state.GetStateObject([]byte("aa"))
if !stateObject.GetStorage(ethutil.Big("0")).Cmp(ethutil.NewValue(42)) {
t.Error("Expected storage 0 to be 42")
}
}

View File

@ -1,6 +1,7 @@
package ethchain package ethchain
import ( import (
"fmt"
"github.com/ethereum/eth-go/ethutil" "github.com/ethereum/eth-go/ethutil"
"github.com/obscuren/secp256k1-go" "github.com/obscuren/secp256k1-go"
"math/big" "math/big"
@ -15,7 +16,6 @@ type Transaction struct {
Gas *big.Int Gas *big.Int
GasPrice *big.Int GasPrice *big.Int
Data []byte Data []byte
Init []byte
v byte v byte
r, s []byte r, s []byte
@ -23,8 +23,8 @@ type Transaction struct {
contractCreation bool contractCreation bool
} }
func NewContractCreationTx(value, gas, gasPrice *big.Int, script []byte, init []byte) *Transaction { func NewContractCreationTx(value, gas, gasPrice *big.Int, script []byte) *Transaction {
return &Transaction{Value: value, Gas: gas, GasPrice: gasPrice, Data: script, Init: init, contractCreation: true} return &Transaction{Value: value, Gas: gas, GasPrice: gasPrice, Data: script, contractCreation: true}
} }
func NewTransactionMessage(to []byte, value, gas, gasPrice *big.Int, data []byte) *Transaction { func NewTransactionMessage(to []byte, value, gas, gasPrice *big.Int, data []byte) *Transaction {
@ -46,19 +46,26 @@ func NewTransactionFromValue(val *ethutil.Value) *Transaction {
} }
func (tx *Transaction) Hash() []byte { func (tx *Transaction) Hash() []byte {
data := []interface{}{tx.Nonce, tx.Value, tx.GasPrice, tx.Gas, tx.Recipient, tx.Data} data := []interface{}{tx.Nonce, tx.GasPrice, tx.Gas, tx.Recipient, tx.Value, tx.Data}
/*
if tx.contractCreation { if tx.contractCreation {
data = append(data, tx.Init) data = append(data, tx.Init)
} }
*/
return ethutil.Sha3Bin(ethutil.NewValue(data).Encode()) return ethutil.Sha3Bin(ethutil.NewValue(data).Encode())
} }
func (tx *Transaction) IsContract() bool { func (tx *Transaction) CreatesContract() bool {
return tx.contractCreation return tx.contractCreation
} }
/* Depricated */
func (tx *Transaction) IsContract() bool {
return tx.CreatesContract()
}
func (tx *Transaction) CreationAddress() []byte { func (tx *Transaction) CreationAddress() []byte {
return ethutil.Sha3Bin(ethutil.NewValue([]interface{}{tx.Sender(), tx.Nonce}).Encode())[12:] return ethutil.Sha3Bin(ethutil.NewValue([]interface{}{tx.Sender(), tx.Nonce}).Encode())[12:]
} }
@ -112,10 +119,6 @@ func (tx *Transaction) Sign(privk []byte) error {
func (tx *Transaction) RlpData() interface{} { func (tx *Transaction) RlpData() interface{} {
data := []interface{}{tx.Nonce, tx.GasPrice, tx.Gas, tx.Recipient, tx.Value, tx.Data} data := []interface{}{tx.Nonce, tx.GasPrice, tx.Gas, tx.Recipient, tx.Value, tx.Data}
if tx.contractCreation {
data = append(data, tx.Init)
}
return append(data, tx.v, tx.r, tx.s) return append(data, tx.v, tx.r, tx.s)
} }
@ -138,7 +141,14 @@ func (tx *Transaction) RlpValueDecode(decoder *ethutil.Value) {
tx.Recipient = decoder.Get(3).Bytes() tx.Recipient = decoder.Get(3).Bytes()
tx.Value = decoder.Get(4).BigInt() tx.Value = decoder.Get(4).BigInt()
tx.Data = decoder.Get(5).Bytes() 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()
if len(tx.Recipient) == 0 {
tx.contractCreation = true
}
/*
// If the list is of length 10 it's a contract creation tx // If the list is of length 10 it's a contract creation tx
if decoder.Len() == 10 { if decoder.Len() == 10 {
tx.contractCreation = true tx.contractCreation = true
@ -152,4 +162,69 @@ func (tx *Transaction) RlpValueDecode(decoder *ethutil.Value) {
tx.r = decoder.Get(7).Bytes() tx.r = decoder.Get(7).Bytes()
tx.s = decoder.Get(8).Bytes() tx.s = decoder.Get(8).Bytes()
} }
*/
}
func (tx *Transaction) String() string {
return fmt.Sprintf(`
TX(%x)
Contract: %v
From: %x
To: %x
Nonce: %v
GasPrice: %v
Gas: %v
Value: %v
Data: 0x%x
V: 0x%x
R: 0x%x
S: 0x%x
`,
tx.Hash(),
len(tx.Recipient) == 0,
tx.Sender(),
tx.Recipient,
tx.Nonce,
tx.GasPrice,
tx.Gas,
tx.Value,
tx.Data,
tx.v,
tx.r,
tx.s)
}
type Receipt struct {
Tx *Transaction
PostState []byte
CumulativeGasUsed *big.Int
}
func NewRecieptFromValue(val *ethutil.Value) *Receipt {
r := &Receipt{}
r.RlpValueDecode(val)
return r
}
func (self *Receipt) RlpValueDecode(decoder *ethutil.Value) {
self.Tx = NewTransactionFromValue(decoder.Get(0))
self.PostState = decoder.Get(1).Bytes()
self.CumulativeGasUsed = decoder.Get(2).BigInt()
}
func (self *Receipt) RlpData() interface{} {
return []interface{}{self.Tx.RlpData(), self.PostState, self.CumulativeGasUsed}
}
func (self *Receipt) String() string {
return fmt.Sprintf(`
R
Tx:[ %v]
PostState: 0x%x
CumulativeGasUsed: %v
`,
self.Tx,
self.PostState,
self.CumulativeGasUsed)
} }

View File

@ -91,15 +91,15 @@ func (pool *TxPool) addTransaction(tx *Transaction) {
// Process transaction validates the Tx and processes funds from the // Process transaction validates the Tx and processes funds from the
// sender to the recipient. // sender to the recipient.
func (pool *TxPool) ProcessTransaction(tx *Transaction, block *Block, toContract bool) (err error) { func (pool *TxPool) ProcessTransaction(tx *Transaction, state *State, toContract bool) (err error) {
defer func() { defer func() {
if r := recover(); r != nil { if r := recover(); r != nil {
log.Println(r) ethutil.Config.Log.Infoln(r)
err = fmt.Errorf("%v", r) err = fmt.Errorf("%v", r)
} }
}() }()
// Get the sender // Get the sender
sender := block.state.GetAccount(tx.Sender()) sender := state.GetAccount(tx.Sender())
if sender.Nonce != tx.Nonce { if sender.Nonce != tx.Nonce {
return fmt.Errorf("[TXPL] Invalid account nonce, state nonce is %d transaction nonce is %d instead", sender.Nonce, tx.Nonce) return fmt.Errorf("[TXPL] Invalid account nonce, state nonce is %d transaction nonce is %d instead", sender.Nonce, tx.Nonce)
@ -107,19 +107,21 @@ func (pool *TxPool) ProcessTransaction(tx *Transaction, block *Block, toContract
// 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.
totAmount := new(big.Int).Add(tx.Value, new(big.Int).Mul(TxFee, TxFeeRat)) //totAmount := new(big.Int).Add(tx.Value, new(big.Int).Mul(TxFee, TxFeeRat))
totAmount := new(big.Int).Add(tx.Value, new(big.Int).Mul(tx.Gas, tx.GasPrice))
if sender.Amount.Cmp(totAmount) < 0 { if sender.Amount.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())
} }
//fmt.Println(tx)
// Get the receiver // Get the receiver
receiver := block.state.GetAccount(tx.Recipient) receiver := state.GetAccount(tx.Recipient)
sender.Nonce += 1 sender.Nonce += 1
// Send Tx to self // Send Tx to self
if bytes.Compare(tx.Recipient, tx.Sender()) == 0 { if bytes.Compare(tx.Recipient, tx.Sender()) == 0 {
// Subtract the fee // Subtract the fee
sender.SubAmount(new(big.Int).Mul(TxFee, TxFeeRat)) sender.SubAmount(new(big.Int).Mul(GasTx, tx.GasPrice))
} else { } else {
// Subtract the amount from the senders account // Subtract the amount from the senders account
sender.SubAmount(totAmount) sender.SubAmount(totAmount)
@ -127,10 +129,10 @@ func (pool *TxPool) ProcessTransaction(tx *Transaction, block *Block, toContract
// Add the amount to receivers account which should conclude this transaction // Add the amount to receivers account which should conclude this transaction
receiver.AddAmount(tx.Value) receiver.AddAmount(tx.Value)
block.state.UpdateStateObject(receiver) state.UpdateStateObject(receiver)
} }
block.state.UpdateStateObject(sender) state.UpdateStateObject(sender)
ethutil.Config.Log.Infof("[TXPL] Processed Tx %x\n", tx.Hash()) ethutil.Config.Log.Infof("[TXPL] Processed Tx %x\n", tx.Hash())

View File

@ -322,3 +322,10 @@ func IsOpCode(s string) bool {
} }
return false return false
} }
func AppendScript(init, script []byte) []byte {
s := append(init, byte(oRETURN))
s = append(s, script...)
return s
}

View File

@ -18,6 +18,7 @@ var (
GasCreate = big.NewInt(100) GasCreate = big.NewInt(100)
GasCall = big.NewInt(20) GasCall = big.NewInt(20)
GasMemory = big.NewInt(1) GasMemory = big.NewInt(1)
GasTx = big.NewInt(500)
) )
func CalculateTxGas(initSize, scriptSize *big.Int) *big.Int { func CalculateTxGas(initSize, scriptSize *big.Int) *big.Int {
@ -425,6 +426,10 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro
value := stack.Pop() value := stack.Pop()
size, offset := stack.Popn() size, offset := stack.Popn()
// Snapshot the current stack so we are able to
// revert back to it later.
snapshot := vm.state.Snapshot()
// Generate a new address // Generate a new address
addr := ethutil.CreateAddress(closure.callee.Address(), closure.callee.N()) addr := ethutil.CreateAddress(closure.callee.Address(), closure.callee.N())
// Create a new contract // Create a new contract
@ -447,6 +452,9 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro
closure.Script, err = closure.Call(vm, nil, hook) closure.Script, err = closure.Call(vm, nil, hook)
if err != nil { if err != nil {
stack.Push(ethutil.BigFalse) stack.Push(ethutil.BigFalse)
// Revert the state as it was before.
vm.state.Revert(snapshot)
} else { } else {
stack.Push(ethutil.BigD(addr)) stack.Push(ethutil.BigD(addr))
@ -472,6 +480,8 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro
// Get the arguments from the memory // Get the arguments from the memory
args := mem.Get(inOffset.Int64(), inSize.Int64()) args := mem.Get(inOffset.Int64(), inSize.Int64())
snapshot := vm.state.Snapshot()
// Fetch the contract which will serve as the closure body // Fetch the contract which will serve as the closure body
contract := vm.state.GetStateObject(addr.Bytes()) contract := vm.state.GetStateObject(addr.Bytes())
@ -494,14 +504,14 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro
if err != nil { if err != nil {
stack.Push(ethutil.BigFalse) stack.Push(ethutil.BigFalse)
// Reset the changes applied this object // Reset the changes applied this object
//contract.State().Reset() vm.state.Revert(snapshot)
} else { } else {
stack.Push(ethutil.BigTrue) stack.Push(ethutil.BigTrue)
}
vm.state.UpdateStateObject(contract) vm.state.UpdateStateObject(contract)
mem.Set(retOffset.Int64(), retSize.Int64(), ret) mem.Set(retOffset.Int64(), retSize.Int64(), ret)
}
} else { } else {
ethutil.Config.Log.Debugf("Contract %x not found\n", addr.Bytes()) ethutil.Config.Log.Debugf("Contract %x not found\n", addr.Bytes())
stack.Push(ethutil.BigFalse) stack.Push(ethutil.BigFalse)

View File

@ -1,6 +1,5 @@
package ethchain package ethchain
/*
import ( import (
_ "bytes" _ "bytes"
"fmt" "fmt"
@ -13,60 +12,33 @@ import (
) )
func TestRun4(t *testing.T) { func TestRun4(t *testing.T) {
ethutil.ReadConfig("", ethutil.LogStd) ethutil.ReadConfig("", ethutil.LogStd, "")
db, _ := ethdb.NewMemDatabase() db, _ := ethdb.NewMemDatabase()
state := NewState(ethutil.NewTrie(db, "")) state := NewState(ethutil.NewTrie(db, ""))
script, err := mutan.Compile(strings.NewReader(`
int32 a = 10
int32 b = 20
if a > b {
int32 c = this.caller()
}
exit()
`), false)
tx := NewContractCreationTx(ethutil.Big("0"), ethutil.Big("1000"), ethutil.Big("100"), script, nil)
tx.Sign(ContractAddr)
addr := tx.CreationAddress()
contract := MakeContract(tx, state)
state.UpdateStateObject(contract)
fmt.Printf("%x\n", addr)
callerScript, err := mutan.Compile(strings.NewReader(` callerScript, err := mutan.Compile(strings.NewReader(`
// Check if there's any cash in the initial store this.store[this.origin()] = 10**20
if this.store[1000] == 0 { hello := "world"
this.store[1000] = 10**20
return lambda {
big to = this.data[0]
big from = this.origin()
big value = this.data[1]
if this.store[from] >= value {
this.store[from] = this.store[from] - value
this.store[to] = this.store[to] + value
} }
this.store[1001] = this.value() * 20
this.store[this.origin()] = this.store[this.origin()] + 1000
if this.store[1001] > 20 {
this.store[1001] = 10^50
}
int8 ret = 0
int8 arg = 10
call(0xe6a12555fad1fb6eaaaed69001a87313d1fd7b54, 0, 100, arg, ret)
big t
for int8 i = 0; i < 10; i++ {
t = i
}
if 10 > 20 {
int8 shouldnt = 2
} else {
int8 should = 1
} }
`), false) `), false)
if err != nil { if err != nil {
fmt.Println(err) fmt.Println(err)
} }
fmt.Println(Disassemble(callerScript))
callerTx := NewContractCreationTx(ethutil.Big("0"), ethutil.Big("1000"), ethutil.Big("100"), callerScript, nil) callerTx := NewContractCreationTx(ethutil.Big("0"), ethutil.Big("1000"), ethutil.Big("100"), callerScript)
callerTx.Sign([]byte("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"))
// Contract addr as test address // Contract addr as test address
gas := big.NewInt(1000) gas := big.NewInt(1000)
@ -79,7 +51,7 @@ func TestRun4(t *testing.T) {
fmt.Println(err) fmt.Println(err)
} }
fmt.Println("account.Amount =", account.Amount) fmt.Println("account.Amount =", account.Amount)
callerClosure := NewClosure(account, c, c.script, state, gas, gasPrice) callerClosure := NewClosure(account, c, callerScript, state, gas, gasPrice)
vm := NewVm(state, nil, RuntimeVars{ vm := NewVm(state, nil, RuntimeVars{
Origin: account.Address(), Origin: account.Address(),
@ -89,10 +61,10 @@ func TestRun4(t *testing.T) {
Time: 1, Time: 1,
Diff: big.NewInt(256), Diff: big.NewInt(256),
}) })
_, e = callerClosure.Call(vm, nil, nil) var ret []byte
ret, e = callerClosure.Call(vm, nil, nil)
if e != nil { if e != nil {
fmt.Println("error", e) fmt.Println("error", e)
} }
fmt.Println("account.Amount =", account.Amount) fmt.Println(ret)
} }
*/

View File

@ -48,7 +48,7 @@ func NewDefaultMiner(coinbase []byte, ethereum ethchain.EthManager) Miner {
// Insert initial TXs in our little miner 'pool' // Insert initial TXs in our little miner 'pool'
miner.txs = ethereum.TxPool().Flush() miner.txs = ethereum.TxPool().Flush()
miner.block = ethereum.BlockChain().NewBlock(miner.coinbase, miner.txs) miner.block = ethereum.BlockChain().NewBlock(miner.coinbase)
return miner return miner
} }
@ -86,7 +86,7 @@ out:
miner.txs = newtxs miner.txs = newtxs
// Setup a fresh state to mine on // Setup a fresh state to mine on
miner.block = miner.ethereum.BlockChain().NewBlock(miner.coinbase, miner.txs) //miner.block = miner.ethereum.BlockChain().NewBlock(miner.coinbase, miner.txs)
} else { } else {
if bytes.Compare(block.PrevHash, miner.ethereum.BlockChain().CurrentBlock.PrevHash) == 0 { if bytes.Compare(block.PrevHash, miner.ethereum.BlockChain().CurrentBlock.PrevHash) == 0 {
@ -125,7 +125,7 @@ func (self *Miner) Stop() {
func (self *Miner) mineNewBlock() { func (self *Miner) mineNewBlock() {
stateManager := self.ethereum.StateManager() stateManager := self.ethereum.StateManager()
self.block = self.ethereum.BlockChain().NewBlock(self.coinbase, self.txs) self.block = self.ethereum.BlockChain().NewBlock(self.coinbase)
// Apply uncles // Apply uncles
if len(self.uncles) > 0 { if len(self.uncles) > 0 {
@ -133,15 +133,10 @@ func (self *Miner) mineNewBlock() {
} }
// Accumulate all valid transaction and apply them to the new state // Accumulate all valid transaction and apply them to the new state
var txs []*ethchain.Transaction receipts, txs := stateManager.ApplyTransactions(self.block.State(), self.block, self.txs)
for _, tx := range self.txs {
if err := stateManager.ApplyTransaction(self.block.State(), self.block, tx); err == nil {
txs = append(txs, tx)
}
}
self.txs = txs self.txs = txs
// Set the transactions to the block so the new SHA3 can be calculated // Set the transactions to the block so the new SHA3 can be calculated
self.block.SetTransactions(self.txs) self.block.SetReceipts(receipts, txs)
// Accumulate the rewards included for this block // Accumulate the rewards included for this block
stateManager.AccumelateRewards(self.block.State(), self.block) stateManager.AccumelateRewards(self.block.State(), self.block)

View File

@ -87,14 +87,14 @@ func (lib *PEthereum) SecretToAddress(key string) string {
} }
func (lib *PEthereum) Transact(key, recipient, valueStr, gasStr, gasPriceStr, dataStr string) (*PReceipt, error) { func (lib *PEthereum) Transact(key, recipient, valueStr, gasStr, gasPriceStr, dataStr string) (*PReceipt, error) {
return lib.createTx(key, recipient, valueStr, gasStr, gasPriceStr, dataStr, "") return lib.createTx(key, recipient, valueStr, gasStr, gasPriceStr, dataStr)
} }
func (lib *PEthereum) Create(key, valueStr, gasStr, gasPriceStr, initStr, bodyStr string) (*PReceipt, error) { func (lib *PEthereum) Create(key, valueStr, gasStr, gasPriceStr, script string) (*PReceipt, error) {
return lib.createTx(key, "", valueStr, gasStr, gasPriceStr, initStr, bodyStr) return lib.createTx(key, "", valueStr, gasStr, gasPriceStr, script)
} }
func (lib *PEthereum) createTx(key, recipient, valueStr, gasStr, gasPriceStr, initStr, scriptStr string) (*PReceipt, error) { func (lib *PEthereum) createTx(key, recipient, valueStr, gasStr, gasPriceStr, scriptStr string) (*PReceipt, error) {
var hash []byte var hash []byte
var contractCreation bool var contractCreation bool
if len(recipient) == 0 { if len(recipient) == 0 {
@ -121,6 +121,7 @@ func (lib *PEthereum) createTx(key, recipient, valueStr, gasStr, gasPriceStr, in
var tx *ethchain.Transaction var tx *ethchain.Transaction
// Compile and assemble the given data // Compile and assemble the given data
if contractCreation { if contractCreation {
/*
var initScript, mainScript []byte var initScript, mainScript []byte
var err error var err error
if ethutil.IsHex(initStr) { if ethutil.IsHex(initStr) {
@ -141,13 +142,26 @@ func (lib *PEthereum) createTx(key, recipient, valueStr, gasStr, gasPriceStr, in
} }
} }
tx = ethchain.NewContractCreationTx(value, gas, gasPrice, mainScript, initScript) script := ethchain.AppendScript(initScript, mainScript)
*/
var script []byte
var err error
if ethutil.IsHex(scriptStr) {
script = ethutil.FromHex(scriptStr)
} else {
script, err = ethutil.Compile(scriptStr)
if err != nil {
return nil, err
}
}
tx = ethchain.NewContractCreationTx(value, gas, gasPrice, script)
} else { } else {
// Just in case it was submitted as a 0x prefixed string // Just in case it was submitted as a 0x prefixed string
if len(initStr) > 0 && initStr[0:2] == "0x" { if len(scriptStr) > 0 && scriptStr[0:2] == "0x" {
initStr = initStr[2:len(initStr)] scriptStr = scriptStr[2:len(scriptStr)]
} }
tx = ethchain.NewTransactionMessage(hash, value, gas, gasPrice, ethutil.FromHex(initStr)) tx = ethchain.NewTransactionMessage(hash, value, gas, gasPrice, ethutil.FromHex(scriptStr))
} }
acc := lib.stateManager.TransState().GetStateObject(keyPair.Address()) acc := lib.stateManager.TransState().GetStateObject(keyPair.Address())

View File

@ -31,7 +31,18 @@ func (self *PBlock) ToString() string {
return "" return ""
} }
func (self *PBlock) GetTransaction(hash string) *PTx {
tx := self.ref.GetTransaction(ethutil.FromHex(hash))
if tx == nil {
return nil
}
return NewPTx(tx)
}
type PTx struct { type PTx struct {
ref *ethchain.Transaction
Value, Hash, Address string Value, Hash, Address string
Contract bool Contract bool
} }
@ -41,7 +52,11 @@ func NewPTx(tx *ethchain.Transaction) *PTx {
sender := hex.EncodeToString(tx.Recipient) sender := hex.EncodeToString(tx.Recipient)
isContract := len(tx.Data) > 0 isContract := len(tx.Data) > 0
return &PTx{Hash: hash, Value: ethutil.CurrencyToString(tx.Value), Address: sender, Contract: isContract} return &PTx{ref: tx, Hash: hash, Value: ethutil.CurrencyToString(tx.Value), Address: sender, Contract: isContract}
}
func (self *PTx) ToString() string {
return self.ref.String()
} }
type PKey struct { type PKey struct {

View File

@ -137,7 +137,7 @@ func (p *EthereumApi) Create(args *NewTxArgs, reply *string) error {
if err != nil { if err != nil {
return err return err
} }
result, _ := p.ethp.Create(p.ethp.GetKey().PrivateKey, args.Value, args.Gas, args.GasPrice, args.Init, args.Body) result, _ := p.ethp.Create(p.ethp.GetKey().PrivateKey, args.Value, args.Gas, args.GasPrice, args.Body)
*reply = NewSuccessRes(result) *reply = NewSuccessRes(result)
return nil return nil
} }

View File

@ -19,6 +19,7 @@ type config struct {
Ver string Ver string
ClientString string ClientString string
Pubkey []byte Pubkey []byte
Identifier string
} }
var Config *config var Config *config
@ -26,7 +27,7 @@ var Config *config
// Read config // Read config
// //
// Initialize the global Config variable with default settings // Initialize the global Config variable with default settings
func ReadConfig(base string, logTypes LoggerType) *config { func ReadConfig(base string, logTypes LoggerType, id string) *config {
if Config == nil { if Config == nil {
usr, _ := user.Current() usr, _ := user.Current()
path := path.Join(usr.HomeDir, base) path := path.Join(usr.HomeDir, base)
@ -42,7 +43,8 @@ func ReadConfig(base string, logTypes LoggerType) *config {
} }
} }
Config = &config{ExecPath: path, Debug: true, Ver: "0.5.0 RC8"} Config = &config{ExecPath: path, Debug: true, Ver: "0.5.0 RC9"}
Config.Identifier = id
Config.Log = NewLogger(logTypes, LogLevelDebug) Config.Log = NewLogger(logTypes, LogLevelDebug)
Config.SetClientString("/Ethereum(G)") Config.SetClientString("/Ethereum(G)")
} }
@ -53,7 +55,11 @@ func ReadConfig(base string, logTypes LoggerType) *config {
// Set client string // Set client string
// //
func (c *config) SetClientString(str string) { func (c *config) SetClientString(str string) {
Config.ClientString = fmt.Sprintf("%s nv%s/%s", str, c.Ver, runtime.GOOS) id := runtime.GOOS
if len(c.Identifier) > 0 {
id = c.Identifier
}
Config.ClientString = fmt.Sprintf("%s nv%s/%s", str, c.Ver, id)
} }
type LoggerType byte type LoggerType byte

View File

@ -1,7 +1,7 @@
package ethutil package ethutil
import ( import (
_ "fmt" "fmt"
"reflect" "reflect"
"testing" "testing"
) )
@ -26,7 +26,6 @@ func (db *MemDatabase) Delete(key []byte) error {
delete(db.db, string(key)) delete(db.db, string(key))
return nil return nil
} }
func (db *MemDatabase) GetKeys() []*Key { return nil }
func (db *MemDatabase) Print() {} func (db *MemDatabase) Print() {}
func (db *MemDatabase) Close() {} func (db *MemDatabase) Close() {}
func (db *MemDatabase) LastKnownTD() []byte { return nil } func (db *MemDatabase) LastKnownTD() []byte { return nil }
@ -171,3 +170,17 @@ func TestTrieIterator(t *testing.T) {
t.Errorf("Expected cached nodes to be deleted") t.Errorf("Expected cached nodes to be deleted")
} }
} }
func TestHashes(t *testing.T) {
_, trie := New()
trie.Update("cat", "dog")
trie.Update("ca", "dude")
trie.Update("doge", "1234567890abcdefghijklmnopqrstuvwxxzABCEFGHIJKLMNOPQRSTUVWXYZ")
trie.Update("dog", "test")
trie.Update("test", "1234567890abcdefghijklmnopqrstuvwxxzABCEFGHIJKLMNOPQRSTUVWXYZ")
fmt.Printf("%x\n", trie.Root)
trie.Delete("dog")
fmt.Printf("%x\n", trie.Root)
trie.Delete("test")
fmt.Printf("%x\n", trie.Root)
}

View File

@ -16,7 +16,7 @@ type Value struct {
} }
func (val *Value) String() string { func (val *Value) String() string {
return fmt.Sprintf("%q", val.Val) return fmt.Sprintf("%x", val.Val)
} }
func NewValue(val interface{}) *Value { func NewValue(val interface{}) *Value {

28
peer.go
View File

@ -18,7 +18,7 @@ const (
// The size of the output buffer for writing messages // The size of the output buffer for writing messages
outputBufferSize = 50 outputBufferSize = 50
// Current protocol version // Current protocol version
ProtocolVersion = 12 ProtocolVersion = 17
) )
type DiscReason byte type DiscReason byte
@ -119,7 +119,7 @@ type Peer struct {
// this to prevent receiving false peers. // this to prevent receiving false peers.
requestedPeerList bool requestedPeerList bool
host []interface{} host []byte
port uint16 port uint16
caps Caps caps Caps
@ -134,8 +134,7 @@ type Peer struct {
} }
func NewPeer(conn net.Conn, ethereum *Ethereum, inbound bool) *Peer { func NewPeer(conn net.Conn, ethereum *Ethereum, inbound bool) *Peer {
data, _ := ethutil.Config.Db.Get([]byte("KeyRing")) pubkey := ethutil.GetKeyRing().Get(0).PublicKey[1:]
pubkey := ethutil.NewValueFromBytes(data).Get(2).Bytes()
return &Peer{ return &Peer{
outputQueue: make(chan *ethwire.Msg, outputBufferSize), outputQueue: make(chan *ethwire.Msg, outputBufferSize),
@ -342,6 +341,7 @@ func (p *Peer) HandleInbound() {
if ethutil.Config.Debug { if ethutil.Config.Debug {
ethutil.Config.Log.Infof("[PEER] Block %x failed\n", block.Hash()) ethutil.Config.Log.Infof("[PEER] Block %x failed\n", block.Hash())
ethutil.Config.Log.Infof("[PEER] %v\n", err) ethutil.Config.Log.Infof("[PEER] %v\n", err)
ethutil.Config.Log.Debugln(block)
} }
break break
} else { } else {
@ -437,7 +437,7 @@ func (p *Peer) HandleInbound() {
// If a parent is found send back a reply // If a parent is found send back a reply
if parent != nil { if parent != nil {
ethutil.Config.Log.Debugf("[PEER] Found conical block, returning chain from: %x ", parent.Hash()) ethutil.Config.Log.Debugf("[PEER] Found canonical block, returning chain from: %x ", parent.Hash())
chain := p.ethereum.BlockChain().GetChainFromHash(parent.Hash(), amountOfBlocks) chain := p.ethereum.BlockChain().GetChainFromHash(parent.Hash(), amountOfBlocks)
if len(chain) > 0 { if len(chain) > 0 {
ethutil.Config.Log.Debugf("[PEER] Returning %d blocks: %x ", len(chain), parent.Hash()) ethutil.Config.Log.Debugf("[PEER] Returning %d blocks: %x ", len(chain), parent.Hash())
@ -531,11 +531,10 @@ func (p *Peer) Stop() {
} }
func (p *Peer) pushHandshake() error { func (p *Peer) pushHandshake() error {
data, _ := ethutil.Config.Db.Get([]byte("KeyRing")) pubkey := ethutil.GetKeyRing().Get(0).PublicKey
pubkey := ethutil.NewValueFromBytes(data).Get(2).Bytes()
msg := ethwire.NewMessage(ethwire.MsgHandshakeTy, []interface{}{ msg := ethwire.NewMessage(ethwire.MsgHandshakeTy, []interface{}{
uint32(ProtocolVersion), uint32(0), p.Version, byte(p.caps), p.port, pubkey, uint32(ProtocolVersion), uint32(0), p.Version, byte(p.caps), p.port, pubkey[1:],
}) })
p.QueueMessage(msg) p.QueueMessage(msg)
@ -667,23 +666,24 @@ func (p *Peer) RlpData() []interface{} {
return []interface{}{p.host, p.port, p.pubkey} return []interface{}{p.host, p.port, p.pubkey}
} }
func packAddr(address, port string) ([]interface{}, uint16) { func packAddr(address, port string) ([]byte, uint16) {
addr := strings.Split(address, ".") addr := strings.Split(address, ".")
a, _ := strconv.Atoi(addr[0]) a, _ := strconv.Atoi(addr[0])
b, _ := strconv.Atoi(addr[1]) b, _ := strconv.Atoi(addr[1])
c, _ := strconv.Atoi(addr[2]) c, _ := strconv.Atoi(addr[2])
d, _ := strconv.Atoi(addr[3]) d, _ := strconv.Atoi(addr[3])
host := []interface{}{int32(a), int32(b), int32(c), int32(d)} host := []byte{byte(a), byte(b), byte(c), byte(d)}
prt, _ := strconv.Atoi(port) prt, _ := strconv.Atoi(port)
return host, uint16(prt) return host, uint16(prt)
} }
func unpackAddr(value *ethutil.Value, p uint64) string { func unpackAddr(value *ethutil.Value, p uint64) string {
a := strconv.Itoa(int(value.Get(0).Uint())) byts := value.Bytes()
b := strconv.Itoa(int(value.Get(1).Uint())) a := strconv.Itoa(int(byts[0]))
c := strconv.Itoa(int(value.Get(2).Uint())) b := strconv.Itoa(int(byts[1]))
d := strconv.Itoa(int(value.Get(3).Uint())) c := strconv.Itoa(int(byts[2]))
d := strconv.Itoa(int(byts[3]))
host := strings.Join([]string{a, b, c, d}, ".") host := strings.Join([]string{a, b, c, d}, ".")
port := strconv.Itoa(int(p)) port := strconv.Itoa(int(p))