Merge branch 'release/poc5-rc6'

pull/150/head
obscuren 11 years ago
commit 6efdd21633
  1. 2
      README.md
  2. 87
      ethchain/keypair.go
  3. 1
      ethchain/state_manager.go
  4. 15
      ethchain/transaction_pool.go
  5. 2
      ethdb/database.go
  6. 2
      ethdb/memory_database.go
  7. 12
      ethereum.go
  8. 13
      ethpub/pub.go
  9. 2
      ethpub/types.go
  10. 2
      ethutil/config.go
  11. 2
      ethutil/db.go
  12. 19
      ethutil/key.go
  13. 109
      ethutil/keypair.go
  14. 3
      ethwire/messaging.go
  15. 48
      peer.go

@ -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.

@ -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
}

@ -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")
} }

@ -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()

@ -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

@ -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))

@ -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
} }

@ -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 {

@ -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)}
} }

@ -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)")
} }

@ -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()

@ -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()
}

@ -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
}

@ -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
} }

@ -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

Loading…
Cancel
Save