Merge branch 'release/poc5-rc6'

This commit is contained in:
obscuren 2014-05-14 21:34:30 +02:00
commit 6efdd21633
15 changed files with 171 additions and 150 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 RC4". For build instructions see the [Wiki](https://github.com/ethereum/go-ethereum/wiki/Building-Ethereum(Go)). of Concept 5.0 RC6". 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,87 +0,0 @@
package ethchain
import (
"github.com/ethereum/eth-go/ethutil"
"github.com/obscuren/secp256k1-go"
"math/big"
)
type KeyPair struct {
PrivateKey []byte
PublicKey []byte
// The associated account
account *StateObject
state *State
}
func NewKeyPairFromSec(seckey []byte) (*KeyPair, error) {
pubkey, err := secp256k1.GeneratePubKey(seckey)
if err != nil {
return nil, err
}
return &KeyPair{PrivateKey: seckey, PublicKey: pubkey}, nil
}
func NewKeyPairFromValue(val *ethutil.Value) *KeyPair {
keyPair := &KeyPair{PrivateKey: val.Get(0).Bytes(), PublicKey: val.Get(1).Bytes()}
return keyPair
}
func (k *KeyPair) Address() []byte {
return ethutil.Sha3Bin(k.PublicKey[1:])[12:]
}
func (k *KeyPair) Account() *StateObject {
if k.account == nil {
k.account = k.state.GetAccount(k.Address())
}
return k.account
}
// Create transaction, creates a new and signed transaction, ready for processing
func (k *KeyPair) CreateTx(receiver []byte, value *big.Int, data []string) *Transaction {
/* TODO
tx := NewTransaction(receiver, value, data)
tx.Nonce = k.account.Nonce
// Sign the transaction with the private key in this key chain
tx.Sign(k.PrivateKey)
return tx
*/
return nil
}
func (k *KeyPair) RlpEncode() []byte {
return ethutil.EmptyValue().Append(k.PrivateKey).Append(k.PublicKey).Encode()
}
type KeyRing struct {
keys []*KeyPair
}
func (k *KeyRing) Add(pair *KeyPair) {
k.keys = append(k.keys, pair)
}
// The public "singleton" keyring
var keyRing *KeyRing
func GetKeyRing(state *State) *KeyRing {
if keyRing == nil {
keyRing = &KeyRing{}
data, _ := ethutil.Config.Db.Get([]byte("KeyRing"))
it := ethutil.NewValueFromBytes(data).NewIterator()
for it.Next() {
v := it.Value()
keyRing.Add(NewKeyPairFromValue(v))
}
}
return keyRing
}

View File

@ -200,6 +200,7 @@ func (sm *StateManager) ProcessBlock(block *Block, dontReact bool) error {
sm.Ethereum.Broadcast(ethwire.MsgBlockTy, []interface{}{block.Value().Val}) sm.Ethereum.Broadcast(ethwire.MsgBlockTy, []interface{}{block.Value().Val})
sm.Ethereum.TxPool().RemoveInvalid(sm.procState)
} else { } else {
fmt.Println("total diff failed") fmt.Println("total diff failed")
} }

View File

@ -210,9 +210,9 @@ func (pool *TxPool) CurrentTransactions() []*Transaction {
txList := make([]*Transaction, pool.pool.Len()) txList := make([]*Transaction, pool.pool.Len())
i := 0 i := 0
for e := pool.pool.Front(); e != nil; e = e.Next() { for e := pool.pool.Front(); e != nil; e = e.Next() {
if tx, ok := e.Value.(*Transaction); ok { tx := e.Value.(*Transaction)
txList[i] = tx
} txList[i] = tx
i++ i++
} }
@ -220,6 +220,17 @@ func (pool *TxPool) CurrentTransactions() []*Transaction {
return txList return txList
} }
func (pool *TxPool) RemoveInvalid(state *State) {
for e := pool.pool.Front(); e != nil; e = e.Next() {
tx := e.Value.(*Transaction)
sender := state.GetAccount(tx.Sender())
err := pool.ValidateTransaction(tx)
if err != nil || sender.Nonce != tx.Nonce {
pool.pool.Remove(e)
}
}
}
func (pool *TxPool) Flush() []*Transaction { func (pool *TxPool) Flush() []*Transaction {
txList := pool.CurrentTransactions() txList := pool.CurrentTransactions()

View File

@ -54,11 +54,13 @@ func (db *LDBDatabase) LastKnownTD() []byte {
return data return data
} }
/*
func (db *LDBDatabase) GetKeys() []*ethutil.Key { func (db *LDBDatabase) GetKeys() []*ethutil.Key {
data, _ := db.Get([]byte("KeyRing")) data, _ := db.Get([]byte("KeyRing"))
return []*ethutil.Key{ethutil.NewKeyFromBytes(data)} return []*ethutil.Key{ethutil.NewKeyFromBytes(data)}
} }
*/
func (db *LDBDatabase) Close() { func (db *LDBDatabase) Close() {
// Close the leveldb database // Close the leveldb database

View File

@ -26,11 +26,13 @@ func (db *MemDatabase) Get(key []byte) ([]byte, error) {
return db.db[string(key)], nil return db.db[string(key)], nil
} }
/*
func (db *MemDatabase) GetKeys() []*ethutil.Key { func (db *MemDatabase) GetKeys() []*ethutil.Key {
data, _ := db.Get([]byte("KeyRing")) data, _ := db.Get([]byte("KeyRing"))
return []*ethutil.Key{ethutil.NewKeyFromBytes(data)} return []*ethutil.Key{ethutil.NewKeyFromBytes(data)}
} }
*/
func (db *MemDatabase) Delete(key []byte) error { func (db *MemDatabase) Delete(key []byte) error {
delete(db.db, string(key)) delete(db.db, string(key))

View File

@ -138,6 +138,18 @@ func (s *Ethereum) IsMining() bool {
func (s *Ethereum) PeerCount() int { func (s *Ethereum) PeerCount() int {
return s.peers.Len() return s.peers.Len()
} }
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 {
upToDate = false
}
}
})
return upToDate
}
func (s *Ethereum) IsListening() bool { func (s *Ethereum) IsListening() bool {
return s.listening return s.listening
} }

View File

@ -39,10 +39,7 @@ func (lib *PEthereum) GetBlock(hexHash string) *PBlock {
} }
func (lib *PEthereum) GetKey() *PKey { func (lib *PEthereum) GetKey() *PKey {
keyPair, err := ethchain.NewKeyPairFromSec(ethutil.Config.Db.GetKeys()[0].PrivateKey) keyPair := ethutil.GetKeyRing().Get(0)
if err != nil {
return nil
}
return NewPKey(keyPair) return NewPKey(keyPair)
} }
@ -90,7 +87,7 @@ func (lib *PEthereum) IsContract(address string) bool {
} }
func (lib *PEthereum) SecretToAddress(key string) string { func (lib *PEthereum) SecretToAddress(key string) string {
pair, err := ethchain.NewKeyPairFromSec(ethutil.FromHex(key)) pair, err := ethutil.NewKeyPairFromSec(ethutil.FromHex(key))
if err != nil { if err != nil {
return "" return ""
} }
@ -115,12 +112,12 @@ func (lib *PEthereum) createTx(key, recipient, valueStr, gasStr, gasPriceStr, in
hash = ethutil.FromHex(recipient) hash = ethutil.FromHex(recipient)
} }
var keyPair *ethchain.KeyPair var keyPair *ethutil.KeyPair
var err error var err error
if key[0:2] == "0x" { if key[0:2] == "0x" {
keyPair, err = ethchain.NewKeyPairFromSec([]byte(ethutil.FromHex(key[0:2]))) keyPair, err = ethutil.NewKeyPairFromSec([]byte(ethutil.FromHex(key[0:2])))
} else { } else {
keyPair, err = ethchain.NewKeyPairFromSec([]byte(ethutil.FromHex(key))) keyPair, err = ethutil.NewKeyPairFromSec([]byte(ethutil.FromHex(key)))
} }
if err != nil { if err != nil {

View File

@ -39,7 +39,7 @@ type PKey struct {
PublicKey string `json:"publicKey"` PublicKey string `json:"publicKey"`
} }
func NewPKey(key *ethchain.KeyPair) *PKey { func NewPKey(key *ethutil.KeyPair) *PKey {
return &PKey{ethutil.Hex(key.Address()), ethutil.Hex(key.PrivateKey), ethutil.Hex(key.PublicKey)} return &PKey{ethutil.Hex(key.Address()), ethutil.Hex(key.PrivateKey), ethutil.Hex(key.PublicKey)}
} }

View File

@ -50,7 +50,7 @@ func ReadConfig(base string) *config {
} }
} }
Config = &config{ExecPath: path, Debug: true, Ver: "0.5.0 RC4"} Config = &config{ExecPath: path, Debug: true, Ver: "0.5.0 RC6"}
Config.Log = NewLogger(LogFile|LogStd, LogLevelDebug) Config.Log = NewLogger(LogFile|LogStd, LogLevelDebug)
Config.SetClientString("/Ethereum(G)") Config.SetClientString("/Ethereum(G)")
} }

View File

@ -4,7 +4,7 @@ package ethutil
type Database interface { type Database interface {
Put(key []byte, value []byte) Put(key []byte, value []byte)
Get(key []byte) ([]byte, error) Get(key []byte) ([]byte, error)
GetKeys() []*Key //GetKeys() []*Key
Delete(key []byte) error Delete(key []byte) error
LastKnownTD() []byte LastKnownTD() []byte
Close() Close()

View File

@ -1,19 +0,0 @@
package ethutil
type Key struct {
PrivateKey []byte
PublicKey []byte
}
func NewKeyFromBytes(data []byte) *Key {
val := NewValueFromBytes(data)
return &Key{val.Get(0).Bytes(), val.Get(1).Bytes()}
}
func (k *Key) Address() []byte {
return Sha3Bin(k.PublicKey[1:])[12:]
}
func (k *Key) RlpEncode() []byte {
return EmptyValue().Append(k.PrivateKey).Append(k.PublicKey).Encode()
}

109
ethutil/keypair.go Normal file
View File

@ -0,0 +1,109 @@
package ethutil
import (
"github.com/obscuren/secp256k1-go"
)
type KeyPair struct {
PrivateKey []byte
PublicKey []byte
// The associated account
account *StateObject
}
func NewKeyPairFromSec(seckey []byte) (*KeyPair, error) {
pubkey, err := secp256k1.GeneratePubKey(seckey)
if err != nil {
return nil, err
}
return &KeyPair{PrivateKey: seckey, PublicKey: pubkey}, nil
}
func NewKeyPairFromValue(val *Value) *KeyPair {
v, _ := NewKeyPairFromSec(val.Bytes())
return v
}
func (k *KeyPair) Address() []byte {
return Sha3Bin(k.PublicKey[1:])[12:]
}
func (k *KeyPair) RlpEncode() []byte {
return k.RlpValue().Encode()
}
func (k *KeyPair) RlpValue() *Value {
return NewValue(k.PrivateKey)
}
type KeyRing struct {
keys []*KeyPair
}
func (k *KeyRing) Add(pair *KeyPair) {
k.keys = append(k.keys, pair)
}
func (k *KeyRing) Get(i int) *KeyPair {
if len(k.keys) > i {
return k.keys[i]
}
return nil
}
func (k *KeyRing) Len() int {
return len(k.keys)
}
func (k *KeyRing) NewKeyPair(sec []byte) (*KeyPair, error) {
keyPair, err := NewKeyPairFromSec(sec)
if err != nil {
return nil, err
}
k.Add(keyPair)
Config.Db.Put([]byte("KeyRing"), k.RlpValue().Encode())
return keyPair, nil
}
func (k *KeyRing) Reset() {
Config.Db.Put([]byte("KeyRing"), nil)
k.keys = nil
}
func (k *KeyRing) RlpValue() *Value {
v := EmptyValue()
for _, keyPair := range k.keys {
v.Append(keyPair.RlpValue())
}
return v
}
// The public "singleton" keyring
var keyRing *KeyRing
func GetKeyRing() *KeyRing {
if keyRing == nil {
keyRing = &KeyRing{}
data, _ := Config.Db.Get([]byte("KeyRing"))
it := NewValueFromBytes(data).NewIterator()
for it.Next() {
v := it.Value()
key, err := NewKeyPairFromSec(v.Bytes())
if err != nil {
panic(err)
}
keyRing.Add(key)
}
}
return keyRing
}

View File

@ -124,7 +124,7 @@ func ReadMessages(conn net.Conn) (msgs []*Msg, err error) {
var totalBytes int var totalBytes int
for { for {
// Give buffering some time // Give buffering some time
conn.SetReadDeadline(time.Now().Add(20 * time.Millisecond)) conn.SetReadDeadline(time.Now().Add(500 * time.Millisecond))
// Create a new temporarily buffer // Create a new temporarily buffer
b := make([]byte, 1440) b := make([]byte, 1440)
// Wait for a message from this peer // Wait for a message from this peer
@ -134,7 +134,6 @@ func ReadMessages(conn net.Conn) (msgs []*Msg, err error) {
fmt.Println("err now", err) fmt.Println("err now", err)
return nil, err return nil, err
} else { } else {
fmt.Println("IOF NOW")
break break
} }

48
peer.go
View File

@ -187,6 +187,10 @@ func NewOutboundPeer(addr string, ethereum *Ethereum, caps Caps) *Peer {
// Outputs any RLP encoded data to the peer // Outputs any RLP encoded data to the peer
func (p *Peer) QueueMessage(msg *ethwire.Msg) { func (p *Peer) QueueMessage(msg *ethwire.Msg) {
if atomic.LoadInt32(&p.connected) != 1 {
return
}
p.outputQueue <- msg p.outputQueue <- msg
} }
@ -295,28 +299,6 @@ func (p *Peer) HandleInbound() {
var block, lastBlock *ethchain.Block var block, lastBlock *ethchain.Block
var err error var err error
// 1. Compare the first block over the wire's prev-hash with the hash of your last block
// 2. If these two values are the same you can just link the chains together.
// [1:0,2:1,3:2] <- Current blocks (format block:previous_block)
// [1:0,2:1,3:2,4:3,5:4] <- incoming blocks
// == [1,2,3,4,5]
// 3. If the values are not the same we will have to go back and calculate the chain with the highest total difficulty
// [1:0,2:1,3:2,11:3,12:11,13:12]
// [1:0,2:1,3:2,4:3,5:4,6:5]
// [3:2,11:3,12:11,13:12]
// [3:2,4:3,5:4,6:5]
// Heb ik dit blok?
// Nee: heb ik een blok met PrevHash 3?
// Ja: DIVERSION
// Nee; Adding to chain
// See if we can find a common ancestor
// 1. Get the earliest block in the package.
// 2. Do we have this block?
// 3. Yes: Let's continue what we are doing
// 4. No: Let's request more blocks back.
// Make sure we are actually receiving anything // Make sure we are actually receiving anything
if msg.Data.Len()-1 > 1 && p.catchingUp { if msg.Data.Len()-1 > 1 && p.catchingUp {
// We requested blocks and now we need to make sure we have a common ancestor somewhere in these blocks so we can find // We requested blocks and now we need to make sure we have a common ancestor somewhere in these blocks so we can find
@ -338,7 +320,6 @@ func (p *Peer) HandleInbound() {
if !p.ethereum.StateManager().BlockChain().HasBlock(block.Hash()) { if !p.ethereum.StateManager().BlockChain().HasBlock(block.Hash()) {
// We don't have this block, but we do have a block with the same prevHash, diversion time! // We don't have this block, but we do have a block with the same prevHash, diversion time!
if p.ethereum.StateManager().BlockChain().HasBlockWithPrevHash(block.PrevHash) { if p.ethereum.StateManager().BlockChain().HasBlockWithPrevHash(block.PrevHash) {
//ethutil.Config.Log.Infof("[PEER] Local and foreign chain have diverted after %x, finding best chain!\n", block.PrevHash)
if p.ethereum.StateManager().BlockChain().FindCanonicalChainFromMsg(msg, block.PrevHash) { if p.ethereum.StateManager().BlockChain().FindCanonicalChainFromMsg(msg, block.PrevHash) {
return return
} }
@ -371,7 +352,8 @@ func (p *Peer) HandleInbound() {
p.catchingUp = false p.catchingUp = false
p.CatchupWithPeer(p.ethereum.BlockChain().CurrentBlock.Hash()) p.CatchupWithPeer(p.ethereum.BlockChain().CurrentBlock.Hash())
} else if ethchain.IsValidationErr(err) { } else if ethchain.IsValidationErr(err) {
// TODO fmt.Println(err)
p.catchingUp = false
} }
} else { } else {
// XXX Do we want to catch up if there were errors? // XXX Do we want to catch up if there were errors?
@ -381,10 +363,19 @@ func (p *Peer) HandleInbound() {
blockInfo := lastBlock.BlockInfo() blockInfo := lastBlock.BlockInfo()
ethutil.Config.Log.Infof("Synced to block height #%d %x %x\n", blockInfo.Number, lastBlock.Hash(), blockInfo.Hash) ethutil.Config.Log.Infof("Synced to block height #%d %x %x\n", blockInfo.Number, lastBlock.Hash(), blockInfo.Hash)
} }
p.catchingUp = false p.catchingUp = false
p.CatchupWithPeer(p.ethereum.BlockChain().CurrentBlock.Hash())
hash := p.ethereum.BlockChain().CurrentBlock.Hash()
p.CatchupWithPeer(hash)
} }
} }
if msg.Data.Len() == 0 {
// Set catching up to false if
// the peer has nothing left to give
p.catchingUp = false
}
case ethwire.MsgTxTy: case ethwire.MsgTxTy:
// If the message was a transaction queue the transaction // If the message was a transaction queue the transaction
// in the TxPool where it will undergo validation and // in the TxPool where it will undergo validation and
@ -447,7 +438,10 @@ func (p *Peer) HandleInbound() {
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())
p.QueueMessage(ethwire.NewMessage(ethwire.MsgBlockTy, chain)) p.QueueMessage(ethwire.NewMessage(ethwire.MsgBlockTy, chain))
} else {
p.QueueMessage(ethwire.NewMessage(ethwire.MsgBlockTy, []interface{}{}))
} }
} else { } else {
ethutil.Config.Log.Debugf("[PEER] Could not find a similar block") ethutil.Config.Log.Debugf("[PEER] Could not find a similar block")
// If no blocks are found we send back a reply with msg not in chain // If no blocks are found we send back a reply with msg not in chain
@ -577,8 +571,8 @@ func (p *Peer) handleHandshake(msg *ethwire.Msg) {
p.port = uint16(c.Get(4).Uint()) p.port = uint16(c.Get(4).Uint())
// Self connect detection // Self connect detection
key := ethutil.Config.Db.GetKeys()[0] keyPair := ethutil.GetKeyRing().Get(0)
if bytes.Compare(key.PublicKey, p.pubkey) == 0 { if bytes.Compare(keyPair.PublicKey, p.pubkey) == 0 {
p.Stop() p.Stop()
return return