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 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
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.TxPool().RemoveInvalid(sm.procState)
} else {
fmt.Println("total diff failed")
}

View File

@ -210,9 +210,9 @@ func (pool *TxPool) CurrentTransactions() []*Transaction {
txList := make([]*Transaction, pool.pool.Len())
i := 0
for e := pool.pool.Front(); e != nil; e = e.Next() {
if tx, ok := e.Value.(*Transaction); ok {
txList[i] = tx
}
tx := e.Value.(*Transaction)
txList[i] = tx
i++
}
@ -220,6 +220,17 @@ func (pool *TxPool) CurrentTransactions() []*Transaction {
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 {
txList := pool.CurrentTransactions()

View File

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

View File

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

View File

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

View File

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

View File

@ -39,7 +39,7 @@ type PKey struct {
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)}
}

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.SetClientString("/Ethereum(G)")
}

View File

@ -4,7 +4,7 @@ package ethutil
type Database interface {
Put(key []byte, value []byte)
Get(key []byte) ([]byte, error)
GetKeys() []*Key
//GetKeys() []*Key
Delete(key []byte) error
LastKnownTD() []byte
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
for {
// 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
b := make([]byte, 1440)
// 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)
return nil, err
} else {
fmt.Println("IOF NOW")
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
func (p *Peer) QueueMessage(msg *ethwire.Msg) {
if atomic.LoadInt32(&p.connected) != 1 {
return
}
p.outputQueue <- msg
}
@ -295,28 +299,6 @@ func (p *Peer) HandleInbound() {
var block, lastBlock *ethchain.Block
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
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
@ -338,7 +320,6 @@ func (p *Peer) HandleInbound() {
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!
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) {
return
}
@ -371,7 +352,8 @@ func (p *Peer) HandleInbound() {
p.catchingUp = false
p.CatchupWithPeer(p.ethereum.BlockChain().CurrentBlock.Hash())
} else if ethchain.IsValidationErr(err) {
// TODO
fmt.Println(err)
p.catchingUp = false
}
} else {
// XXX Do we want to catch up if there were errors?
@ -381,10 +363,19 @@ func (p *Peer) HandleInbound() {
blockInfo := lastBlock.BlockInfo()
ethutil.Config.Log.Infof("Synced to block height #%d %x %x\n", blockInfo.Number, lastBlock.Hash(), blockInfo.Hash)
}
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:
// If the message was a transaction queue the transaction
// in the TxPool where it will undergo validation and
@ -447,7 +438,10 @@ func (p *Peer) HandleInbound() {
if len(chain) > 0 {
ethutil.Config.Log.Debugf("[PEER] Returning %d blocks: %x ", len(chain), parent.Hash())
p.QueueMessage(ethwire.NewMessage(ethwire.MsgBlockTy, chain))
} else {
p.QueueMessage(ethwire.NewMessage(ethwire.MsgBlockTy, []interface{}{}))
}
} else {
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
@ -577,8 +571,8 @@ func (p *Peer) handleHandshake(msg *ethwire.Msg) {
p.port = uint16(c.Get(4).Uint())
// Self connect detection
key := ethutil.Config.Db.GetKeys()[0]
if bytes.Compare(key.PublicKey, p.pubkey) == 0 {
keyPair := ethutil.GetKeyRing().Get(0)
if bytes.Compare(keyPair.PublicKey, p.pubkey) == 0 {
p.Stop()
return