diff --git a/ethchain/block.go b/ethchain/block.go index 1be8282fa..a0f9ecd86 100644 --- a/ethchain/block.go +++ b/ethchain/block.go @@ -3,6 +3,8 @@ package ethchain import ( "bytes" "fmt" + "github.com/ethereum/eth-go/ethcrypto" + "github.com/ethereum/eth-go/ethtrie" "github.com/ethereum/eth-go/ethutil" "math/big" "strconv" @@ -102,18 +104,18 @@ func CreateBlock(root interface{}, } block.SetUncles([]*Block{}) - block.state = NewState(ethutil.NewTrie(ethutil.Config.Db, root)) + block.state = NewState(ethtrie.NewTrie(ethutil.Config.Db, root)) return block } // Returns a hash of the block func (block *Block) Hash() []byte { - return ethutil.Sha3Bin(block.Value().Encode()) + return ethcrypto.Sha3Bin(block.Value().Encode()) } func (block *Block) HashNoNonce() []byte { - return ethutil.Sha3Bin(ethutil.Encode([]interface{}{block.PrevHash, + return ethcrypto.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})) @@ -239,7 +241,7 @@ func (block *Block) SetUncles(uncles []*Block) { block.Uncles = uncles // Sha of the concatenated uncles - block.UncleSha = ethutil.Sha3Bin(ethutil.Encode(block.rlpUncles())) + block.UncleSha = ethcrypto.Sha3Bin(ethutil.Encode(block.rlpUncles())) } func (self *Block) SetReceipts(receipts []*Receipt, txs []*Transaction) { @@ -250,7 +252,7 @@ func (self *Block) SetReceipts(receipts []*Receipt, txs []*Transaction) { func (block *Block) setTransactions(txs []*Transaction) { block.transactions = txs - trie := ethutil.NewTrie(ethutil.Config.Db, "") + trie := ethtrie.NewTrie(ethutil.Config.Db, "") for i, tx := range txs { trie.Update(strconv.Itoa(i), string(tx.RlpEncode())) } @@ -287,7 +289,7 @@ func (block *Block) RlpValueDecode(decoder *ethutil.Value) { block.PrevHash = header.Get(0).Bytes() block.UncleSha = header.Get(1).Bytes() block.Coinbase = header.Get(2).Bytes() - block.state = NewState(ethutil.NewTrie(ethutil.Config.Db, header.Get(3).Val)) + block.state = NewState(ethtrie.NewTrie(ethutil.Config.Db, header.Get(3).Val)) block.TxSha = header.Get(4).Bytes() block.Difficulty = header.Get(5).BigInt() block.Number = header.Get(6).BigInt() @@ -329,7 +331,7 @@ func NewUncleBlockFromValue(header *ethutil.Value) *Block { block.PrevHash = header.Get(0).Bytes() block.UncleSha = header.Get(1).Bytes() block.Coinbase = header.Get(2).Bytes() - block.state = NewState(ethutil.NewTrie(ethutil.Config.Db, header.Get(3).Val)) + block.state = NewState(ethtrie.NewTrie(ethutil.Config.Db, header.Get(3).Val)) block.TxSha = header.Get(4).Bytes() block.Difficulty = header.Get(5).BigInt() block.Number = header.Get(6).BigInt() diff --git a/ethchain/block_chain.go b/ethchain/block_chain.go index ef56d674c..df735d679 100644 --- a/ethchain/block_chain.go +++ b/ethchain/block_chain.go @@ -278,7 +278,7 @@ func AddTestNetFunds(block *Block) { "e6716f9544a56c530d868e4bfbacb172315bdead", "1a26338f0d905e295fccb71fa9ea849ffa12aaf4", } { - codedAddr := ethutil.FromHex(addr) + codedAddr := ethutil.Hex2Bytes(addr) account := block.state.GetAccount(codedAddr) account.Amount = ethutil.Big("1606938044258990275541962092341162602522202993782792835301376") //ethutil.BigPow(2, 200) block.state.UpdateStateObject(account) diff --git a/ethchain/dagger.go b/ethchain/dagger.go index b586657b9..4dda21ff5 100644 --- a/ethchain/dagger.go +++ b/ethchain/dagger.go @@ -1,6 +1,7 @@ package ethchain import ( + "github.com/ethereum/eth-go/ethcrypto" "github.com/ethereum/eth-go/ethlog" "github.com/ethereum/eth-go/ethutil" "github.com/obscuren/sha3" @@ -41,7 +42,7 @@ func (pow *EasyPow) Search(block *Block, reactChan chan ethutil.React) []byte { powlogger.Infoln("Hashing @", int64(hashes), "khash") } - sha := ethutil.Sha3Bin(big.NewInt(r.Int63()).Bytes()) + sha := ethcrypto.Sha3Bin(big.NewInt(r.Int63()).Bytes()) if pow.Verify(hash, diff, sha) { return sha } diff --git a/ethchain/genesis.go b/ethchain/genesis.go index 359c47c26..54a3bc766 100644 --- a/ethchain/genesis.go +++ b/ethchain/genesis.go @@ -1,6 +1,7 @@ package ethchain import ( + "github.com/ethereum/eth-go/ethcrypto" "github.com/ethereum/eth-go/ethutil" "math/big" ) @@ -11,13 +12,13 @@ import ( var ZeroHash256 = make([]byte, 32) var ZeroHash160 = make([]byte, 20) -var EmptyShaList = ethutil.Sha3Bin(ethutil.Encode([]interface{}{})) +var EmptyShaList = ethcrypto.Sha3Bin(ethutil.Encode([]interface{}{})) var GenesisHeader = []interface{}{ // Previous hash (none) ZeroHash256, // Sha of uncles - ethutil.Sha3Bin(ethutil.Encode([]interface{}{})), + ethcrypto.Sha3Bin(ethutil.Encode([]interface{}{})), // Coinbase ZeroHash160, // Root state @@ -39,7 +40,7 @@ var GenesisHeader = []interface{}{ // Extra nil, // Nonce - ethutil.Sha3Bin(big.NewInt(42).Bytes()), + ethcrypto.Sha3Bin(big.NewInt(42).Bytes()), } var Genesis = []interface{}{GenesisHeader, []interface{}{}, []interface{}{}} diff --git a/ethchain/state.go b/ethchain/state.go index 06a185f59..8b6c2efb8 100644 --- a/ethchain/state.go +++ b/ethchain/state.go @@ -1,6 +1,8 @@ package ethchain import ( + "github.com/ethereum/eth-go/ethcrypto" + "github.com/ethereum/eth-go/ethtrie" "github.com/ethereum/eth-go/ethutil" "math/big" ) @@ -12,7 +14,7 @@ import ( // * Accounts type State struct { // The trie for this structure - trie *ethutil.Trie + trie *ethtrie.Trie stateObjects map[string]*StateObject @@ -20,7 +22,7 @@ type State struct { } // Create a new state from a given trie -func NewState(trie *ethutil.Trie) *State { +func NewState(trie *ethtrie.Trie) *State { return &State{trie: trie, stateObjects: make(map[string]*StateObject), manifest: NewManifest()} } @@ -73,7 +75,7 @@ func (s *State) Purge() int { return s.trie.NewIterator().Purge() } -func (s *State) EachStorage(cb ethutil.EachCallback) { +func (s *State) EachStorage(cb ethtrie.EachCallback) { it := s.trie.NewIterator() it.Each(cb) } @@ -91,7 +93,7 @@ func (self *State) UpdateStateObject(stateObject *StateObject) { self.stateObjects[string(addr)] = stateObject } - ethutil.Config.Db.Put(ethutil.Sha3Bin(stateObject.Script()), stateObject.Script()) + ethutil.Config.Db.Put(ethcrypto.Sha3Bin(stateObject.Script()), stateObject.Script()) self.trie.Update(string(addr), string(stateObject.RlpEncode())) diff --git a/ethchain/state_manager.go b/ethchain/state_manager.go index b0550607f..dea82cae3 100644 --- a/ethchain/state_manager.go +++ b/ethchain/state_manager.go @@ -4,6 +4,7 @@ import ( "bytes" "container/list" "fmt" + "github.com/ethereum/eth-go/ethcrypto" "github.com/ethereum/eth-go/ethlog" "github.com/ethereum/eth-go/ethutil" "github.com/ethereum/eth-go/ethwire" @@ -39,6 +40,7 @@ type EthManager interface { IsMining() bool IsListening() bool Peers() *list.List + KeyManager() *ethcrypto.KeyManager } type StateManager struct { @@ -299,7 +301,7 @@ func (sm *StateManager) ValidateBlock(block *Block) error { // Verify the nonce of the block. Return an error if it's not valid if !sm.Pow.Verify(block.HashNoNonce(), block.Difficulty, block.Nonce) { - return ValidationError("Block's nonce is invalid (= %v)", ethutil.Hex(block.Nonce)) + return ValidationError("Block's nonce is invalid (= %v)", ethutil.Bytes2Hex(block.Nonce)) } return nil diff --git a/ethchain/state_object.go b/ethchain/state_object.go index edac4f6dc..35928c899 100644 --- a/ethchain/state_object.go +++ b/ethchain/state_object.go @@ -2,6 +2,8 @@ package ethchain import ( "fmt" + "github.com/ethereum/eth-go/ethcrypto" + "github.com/ethereum/eth-go/ethtrie" "github.com/ethereum/eth-go/ethutil" "math/big" "strings" @@ -39,7 +41,7 @@ func MakeContract(tx *Transaction, state *State) *StateObject { contract := state.NewStateObject(addr) contract.initScript = tx.Data - contract.state = NewState(ethutil.NewTrie(ethutil.Config.Db, "")) + contract.state = NewState(ethtrie.NewTrie(ethutil.Config.Db, "")) return contract } @@ -49,14 +51,14 @@ func MakeContract(tx *Transaction, state *State) *StateObject { func NewStateObject(addr []byte) *StateObject { object := &StateObject{address: addr, Amount: new(big.Int), gasPool: new(big.Int)} - object.state = NewState(ethutil.NewTrie(ethutil.Config.Db, "")) + object.state = NewState(ethtrie.NewTrie(ethutil.Config.Db, "")) return object } func NewContract(address []byte, Amount *big.Int, root []byte) *StateObject { contract := &StateObject{address: address, Amount: Amount, Nonce: 0} - contract.state = NewState(ethutil.NewTrie(ethutil.Config.Db, string(root))) + contract.state = NewState(ethtrie.NewTrie(ethutil.Config.Db, string(root))) return contract } @@ -249,7 +251,7 @@ func (c *StateObject) RlpEncode() []byte { root = "" } - return ethutil.Encode([]interface{}{c.Nonce, c.Amount, root, ethutil.Sha3Bin(c.script)}) + return ethutil.Encode([]interface{}{c.Nonce, c.Amount, root, ethcrypto.Sha3Bin(c.script)}) } func (c *StateObject) RlpDecode(data []byte) { @@ -257,7 +259,8 @@ func (c *StateObject) RlpDecode(data []byte) { c.Nonce = decoder.Get(0).Uint() c.Amount = decoder.Get(1).BigInt() - c.state = NewState(ethutil.NewTrie(ethutil.Config.Db, decoder.Get(2).Interface())) + c.state = NewState(ethtrie.NewTrie(ethutil.Config.Db, decoder.Get(2).Interface())) + c.state = NewState(ethtrie.NewTrie(ethutil.Config.Db, decoder.Get(2).Interface())) c.ScriptHash = decoder.Get(3).Bytes() diff --git a/ethchain/state_transition.go b/ethchain/state_transition.go index 94c3de3d9..c382bcd60 100644 --- a/ethchain/state_transition.go +++ b/ethchain/state_transition.go @@ -3,6 +3,7 @@ package ethchain import ( "bytes" "fmt" + "github.com/ethereum/eth-go/ethtrie" "github.com/ethereum/eth-go/ethutil" "math/big" ) @@ -268,7 +269,7 @@ func Call(vm *Vm, closure *Closure, data []byte) (ret []byte, err error, deepErr var ( context = closure.object trie = context.state.trie - trie2 = ethutil.NewTrie(ethutil.Config.Db, "") + trie2 = ethtrie.NewTrie(ethutil.Config.Db, "") ) trie.NewIterator().Each(func(key string, v *ethutil.Value) { diff --git a/ethchain/transaction.go b/ethchain/transaction.go index 2ab681030..11f786b36 100644 --- a/ethchain/transaction.go +++ b/ethchain/transaction.go @@ -3,6 +3,7 @@ package ethchain import ( "bytes" "fmt" + "github.com/ethereum/eth-go/ethcrypto" "github.com/ethereum/eth-go/ethutil" "github.com/obscuren/secp256k1-go" "math/big" @@ -62,7 +63,7 @@ func (self *Transaction) TotalValue() *big.Int { func (tx *Transaction) Hash() []byte { data := []interface{}{tx.Nonce, tx.GasPrice, tx.Gas, tx.Recipient, tx.Value, tx.Data} - return ethutil.Sha3Bin(ethutil.NewValue(data).Encode()) + return ethcrypto.Sha3Bin(ethutil.NewValue(data).Encode()) } func (tx *Transaction) CreatesContract() bool { @@ -75,7 +76,7 @@ func (tx *Transaction) IsContract() bool { } func (tx *Transaction) CreationAddress() []byte { - return ethutil.Sha3Bin(ethutil.NewValue([]interface{}{tx.Sender(), tx.Nonce}).Encode())[12:] + return ethcrypto.Sha3Bin(ethutil.NewValue([]interface{}{tx.Sender(), tx.Nonce}).Encode())[12:] } func (tx *Transaction) Signature(key []byte) []byte { @@ -111,7 +112,7 @@ func (tx *Transaction) Sender() []byte { return nil } - return ethutil.Sha3Bin(pubkey[1:])[12:] + return ethcrypto.Sha3Bin(pubkey[1:])[12:] } func (tx *Transaction) Sign(privk []byte) error { diff --git a/ethchain/vm.go b/ethchain/vm.go index 3851d0d70..c5ccb3420 100644 --- a/ethchain/vm.go +++ b/ethchain/vm.go @@ -2,6 +2,7 @@ package ethchain import ( "fmt" + "github.com/ethereum/eth-go/ethcrypto" "github.com/ethereum/eth-go/ethlog" "github.com/ethereum/eth-go/ethutil" "math" @@ -421,7 +422,7 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro case SHA3: require(2) size, offset := stack.Popn() - data := ethutil.Sha3Bin(mem.Get(offset.Int64(), size.Int64())) + data := ethcrypto.Sha3Bin(mem.Get(offset.Int64(), size.Int64())) stack.Push(ethutil.BigD(data)) // 0x30 range @@ -617,7 +618,7 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro snapshot := vm.state.Copy() // Generate a new address - addr := ethutil.CreateAddress(closure.caller.Address(), closure.caller.N()) + addr := ethcrypto.CreateAddress(closure.caller.Address(), closure.caller.N()) vm.Printf(" (*) %x", addr).Endl() diff --git a/ethcrypto/crypto.go b/ethcrypto/crypto.go new file mode 100644 index 000000000..8cb0be88c --- /dev/null +++ b/ethcrypto/crypto.go @@ -0,0 +1,35 @@ +package ethcrypto + +import ( + "code.google.com/p/go.crypto/ripemd160" + "crypto/sha256" + "github.com/obscuren/sha3" + "math/big" +) + +func Sha256Bin(data []byte) []byte { + hash := sha256.Sum256(data) + + return hash[:] +} + +func Ripemd160(data []byte) []byte { + ripemd := ripemd160.New() + ripemd.Write(data) + + return ripemd.Sum(nil) +} + +func Sha3Bin(data []byte) []byte { + d := sha3.NewKeccak256() + d.Write(data) + + return d.Sum(nil) +} + +// Creates an ethereum address given the bytes and the nonce +func CreateAddress(b []byte, nonce *big.Int) []byte { + addrBytes := append(b, nonce.Bytes()...) + + return Sha3Bin(addrBytes)[12:] +} diff --git a/ethcrypto/key_manager.go b/ethcrypto/key_manager.go new file mode 100644 index 000000000..066a62aab --- /dev/null +++ b/ethcrypto/key_manager.go @@ -0,0 +1,129 @@ +package ethcrypto + +import ( + "fmt" + "github.com/ethereum/eth-go/ethutil" + "sync" +) + +type KeyManager struct { + keyRing *KeyRing + session string + keyStore KeyStore // interface + keyRings map[string]*KeyRing // cache + keyPair *KeyPair +} + +func NewDBKeyManager(db ethutil.Database) *KeyManager { + return &KeyManager{keyStore: &DBKeyStore{db: db}, keyRings: make(map[string]*KeyRing)} +} + +func NewFileKeyManager(basedir string) *KeyManager { + return &KeyManager{keyStore: &FileKeyStore{basedir: basedir}, keyRings: make(map[string]*KeyRing)} +} + +func (k *KeyManager) KeyPair() *KeyPair { + return k.keyPair +} + +func (k *KeyManager) KeyRing() *KeyPair { + return k.keyPair +} + +func (k *KeyManager) PrivateKey() []byte { + return k.keyPair.PrivateKey +} + +func (k *KeyManager) PublicKey() []byte { + return k.keyPair.PublicKey +} + +func (k *KeyManager) Address() []byte { + return k.keyPair.Address() +} + +func (k *KeyManager) save(session string, keyRing *KeyRing) error { + err := k.keyStore.Save(session, keyRing) + if err != nil { + return err + } + k.keyRings[session] = keyRing + return nil +} + +func (k *KeyManager) load(session string) (*KeyRing, error) { + keyRing, found := k.keyRings[session] + if !found { + var err error + keyRing, err = k.keyStore.Load(session) + if err != nil { + return nil, err + } + } + return keyRing, nil +} + +func cursorError(cursor int, len int) error { + return fmt.Errorf("cursor %d out of range (0..%d)", cursor, len) +} + +func (k *KeyManager) reset(session string, cursor int, keyRing *KeyRing) error { + if cursor >= keyRing.Len() { + return cursorError(cursor, keyRing.Len()) + } + lock := &sync.Mutex{} + lock.Lock() + defer lock.Unlock() + err := k.save(session, keyRing) + if err != nil { + return err + } + k.session = session + k.keyRing = keyRing + k.keyPair = keyRing.GetKeyPair(cursor) + return nil +} + +func (k *KeyManager) SetCursor(cursor int) error { + if cursor >= k.keyRing.Len() { + return cursorError(cursor, k.keyRing.Len()) + } + k.keyPair = k.keyRing.GetKeyPair(cursor) + return nil +} + +func (k *KeyManager) Init(session string, cursor int, force bool) error { + var keyRing *KeyRing + if !force { + var err error + keyRing, err = k.load(session) + if err != nil { + return err + } + } + if keyRing == nil { + keyRing = NewGeneratedKeyRing(1) + } + return k.reset(session, cursor, keyRing) +} + +func (k *KeyManager) InitFromSecretsFile(session string, cursor int, secretsfile string) error { + keyRing, err := NewKeyRingFromFile(secretsfile) + if err != nil { + return err + } + return k.reset(session, cursor, keyRing) +} + +func (k *KeyManager) InitFromString(session string, cursor int, secrets string) error { + keyRing, err := NewKeyRingFromString(secrets) + if err != nil { + return err + } + return k.reset(session, cursor, keyRing) +} + +func (k *KeyManager) Export(dir string) error { + fileKeyStore := FileKeyStore{dir} + return fileKeyStore.Save(k.session, k.keyRing) +} diff --git a/ethcrypto/key_store.go b/ethcrypto/key_store.go new file mode 100644 index 000000000..460f0c978 --- /dev/null +++ b/ethcrypto/key_store.go @@ -0,0 +1,112 @@ +package ethcrypto + +import ( + "fmt" + "github.com/ethereum/eth-go/ethutil" + "io/ioutil" + "os" + "path" + "strings" +) + +type KeyStore interface { + Load(string) (*KeyRing, error) + Save(string, *KeyRing) error +} + +type DBKeyStore struct { + db ethutil.Database +} + +const dbKeyPrefix = "KeyRing" + +func (k *DBKeyStore) dbKey(session string) []byte { + return []byte(fmt.Sprintf("%s%s", dbKeyPrefix, session)) +} + +func (k *DBKeyStore) Save(session string, keyRing *KeyRing) error { + k.db.Put(k.dbKey(session), keyRing.RlpEncode()) + return nil +} + +func (k *DBKeyStore) Load(session string) (*KeyRing, error) { + data, err := k.db.Get(k.dbKey(session)) + if err != nil { + return nil, nil + } + var keyRing *KeyRing + keyRing, err = NewKeyRingFromBytes(data) + if err != nil { + return nil, err + } + // if empty keyRing is found we return nil, no error + if keyRing.Len() == 0 { + return nil, nil + } + return keyRing, nil +} + +type FileKeyStore struct { + basedir string +} + +func (k *FileKeyStore) Save(session string, keyRing *KeyRing) error { + var content []byte + var err error + var privateKeys []string + var publicKeys []string + var mnemonics []string + var addresses []string + keyRing.Each(func(keyPair *KeyPair) { + privateKeys = append(privateKeys, ethutil.Bytes2Hex(keyPair.PrivateKey)) + publicKeys = append(publicKeys, ethutil.Bytes2Hex(keyPair.PublicKey)) + addresses = append(addresses, ethutil.Bytes2Hex(keyPair.Address())) + mnemonics = append(mnemonics, keyPair.Mnemonic()) + }) + + basename := session + if session == "" { + basename = "default" + } + + path := path.Join(k.basedir, basename) + content = []byte(strings.Join(privateKeys, "\n")) + err = ioutil.WriteFile(path+".prv", content, 0600) + if err != nil { + return err + } + + content = []byte(strings.Join(publicKeys, "\n")) + err = ioutil.WriteFile(path+".pub", content, 0644) + if err != nil { + return err + } + + content = []byte(strings.Join(addresses, "\n")) + err = ioutil.WriteFile(path+".addr", content, 0644) + if err != nil { + return err + } + + content = []byte(strings.Join(mnemonics, "\n")) + err = ioutil.WriteFile(path+".mne", content, 0600) + if err != nil { + return err + } + + return nil +} + +func (k *FileKeyStore) Load(session string) (*KeyRing, error) { + basename := session + if session == "" { + basename = "default" + } + secfile := path.Join(k.basedir, basename+".prv") + _, err := os.Stat(secfile) + // if file is not found then we return nil, no error + if err != nil { + return nil, nil + } + return NewKeyRingFromFile(secfile) +} diff --git a/ethcrypto/keypair.go b/ethcrypto/keypair.go new file mode 100644 index 000000000..18fa5b788 --- /dev/null +++ b/ethcrypto/keypair.go @@ -0,0 +1,57 @@ +package ethcrypto + +import ( + "github.com/ethereum/eth-go/ethutil" + "github.com/obscuren/secp256k1-go" + "strings" +) + +type KeyPair struct { + PrivateKey []byte + PublicKey []byte + address []byte + mnemonic string + // The associated account + // account *StateObject +} + +func GenerateNewKeyPair() *KeyPair { + _, prv := secp256k1.GenerateKeyPair() + keyPair, _ := NewKeyPairFromSec(prv) // swallow error, this one cannot err + return keyPair +} + +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 (k *KeyPair) Address() []byte { + if k.address == nil { + k.address = Sha3Bin(k.PublicKey[1:])[12:] + } + return k.address +} + +func (k *KeyPair) Mnemonic() string { + if k.mnemonic == "" { + k.mnemonic = strings.Join(MnemonicEncode(ethutil.Bytes2Hex(k.PrivateKey)), " ") + } + return k.mnemonic +} + +func (k *KeyPair) AsStrings() (string, string, string, string) { + return k.Mnemonic(), ethutil.Bytes2Hex(k.Address()), ethutil.Bytes2Hex(k.PrivateKey), ethutil.Bytes2Hex(k.PublicKey) +} + +func (k *KeyPair) RlpEncode() []byte { + return k.RlpValue().Encode() +} + +func (k *KeyPair) RlpValue() *ethutil.Value { + return ethutil.NewValue(k.PrivateKey) +} diff --git a/ethcrypto/keyring.go b/ethcrypto/keyring.go new file mode 100644 index 000000000..277fa2134 --- /dev/null +++ b/ethcrypto/keyring.go @@ -0,0 +1,118 @@ +package ethcrypto + +import ( + "fmt" + "github.com/ethereum/eth-go/ethutil" + "io/ioutil" + "strings" +) + +type KeyRing struct { + keys []*KeyPair +} + +func NewKeyRing() *KeyRing { + return &KeyRing{} +} + +func (k *KeyRing) AddKeyPair(keyPair *KeyPair) { + k.keys = append(k.keys, keyPair) +} + +func (k *KeyRing) GetKeyPair(i int) *KeyPair { + if len(k.keys) > i { + return k.keys[i] + } + + return nil +} + +func (k *KeyRing) Empty() bool { + return k.Len() == 0 +} + +func (k *KeyRing) Len() int { + return len(k.keys) +} + +func (k *KeyRing) Each(f func(*KeyPair)) { + for _, keyPair := range k.keys { + f(keyPair) + } +} + +func NewGeneratedKeyRing(len int) *KeyRing { + keyRing := NewKeyRing() + for i := 0; i < len; i++ { + keyRing.AddKeyPair(GenerateNewKeyPair()) + } + return keyRing +} + +func NewKeyRingFromFile(secfile string) (*KeyRing, error) { + var content []byte + var err error + content, err = ioutil.ReadFile(secfile) + if err != nil { + return nil, err + } + keyRing, err := NewKeyRingFromString(string(content)) + if err != nil { + return nil, err + } + return keyRing, nil +} + +func NewKeyRingFromString(content string) (*KeyRing, error) { + secretStrings := strings.Split(content, "\n") + var secrets [][]byte + for _, secretString := range secretStrings { + secret := secretString + words := strings.Split(secretString, " ") + if len(words) == 24 { + secret = MnemonicDecode(words) + } else if len(words) != 1 { + return nil, fmt.Errorf("Unrecognised key format") + } + secrets = append(secrets, ethutil.Hex2Bytes(secret)) + } + return NewKeyRingFromSecrets(secrets) +} + +func NewKeyRingFromSecrets(secs [][]byte) (*KeyRing, error) { + keyRing := NewKeyRing() + for _, sec := range secs { + keyPair, err := NewKeyPairFromSec(sec) + if err != nil { + return nil, err + } + keyRing.AddKeyPair(keyPair) + } + return keyRing, nil +} + +func NewKeyRingFromBytes(data []byte) (*KeyRing, error) { + var secrets [][]byte + it := ethutil.NewValueFromBytes(data).NewIterator() + for it.Next() { + secret := it.Value().Bytes() + secrets = append(secrets, secret) + } + keyRing, err := NewKeyRingFromSecrets(secrets) + if err != nil { + return nil, err + } + return keyRing, nil +} + +func (k *KeyRing) RlpEncode() []byte { + return k.RlpValue().Encode() +} + +func (k *KeyRing) RlpValue() *ethutil.Value { + v := ethutil.EmptyValue() + k.Each(func(keyPair *KeyPair) { + v.Append(keyPair.RlpValue()) + }) + return v +} diff --git a/ethcrypto/keys_test.go b/ethcrypto/keys_test.go new file mode 100644 index 000000000..3ebf4e818 --- /dev/null +++ b/ethcrypto/keys_test.go @@ -0,0 +1,122 @@ +package ethcrypto + +import ( + "github.com/ethereum/eth-go/ethdb" + // "io/ioutil" + "fmt" + "os" + "path" + "testing" +) + +// test if persistence layer works +func TestDBKeyManager(t *testing.T) { + memdb, _ := ethdb.NewMemDatabase() + keyManager0 := NewDBKeyManager(memdb) + err := keyManager0.Init("", 0, false) + if err != nil { + t.Error("Unexpected error: ", err) + } + keyManager1 := NewDBKeyManager(memdb) + err = keyManager1.Init("", 0, false) + if err != nil { + t.Error("Unexpected error: ", err) + } + if string(keyManager0.PrivateKey()) != string(keyManager1.PrivateKey()) { + t.Error("Expected private keys %x, %x, to be identical via db persistence", keyManager0.PrivateKey(), keyManager1.PrivateKey()) + } + err = keyManager1.Init("", 0, true) + if err != nil { + t.Error("Unexpected error: ", err) + } + if string(keyManager0.PrivateKey()) == string(keyManager1.PrivateKey()) { + t.Error("Expected private keys %x, %x, to be be different despite db persistence if force generate", keyManager0.PrivateKey(), keyManager1.PrivateKey()) + } +} + +func TestFileKeyManager(t *testing.T) { + basedir0 := "/tmp/ethtest0" + os.RemoveAll(basedir0) + os.Mkdir(basedir0, 0777) + + keyManager0 := NewFileKeyManager(basedir0) + err := keyManager0.Init("", 0, false) + if err != nil { + t.Error("Unexpected error: ", err) + } + + keyManager1 := NewFileKeyManager(basedir0) + + err = keyManager1.Init("", 0, false) + if err != nil { + t.Error("Unexpected error: ", err) + } + if string(keyManager0.PrivateKey()) != string(keyManager1.PrivateKey()) { + t.Error("Expected private keys %x, %x, to be identical via db persistence", keyManager0.PrivateKey(), keyManager1.PrivateKey()) + } + + err = keyManager1.Init("", 0, true) + if err != nil { + t.Error("Unexpected error: ", err) + } + if string(keyManager0.PrivateKey()) == string(keyManager1.PrivateKey()) { + t.Error("Expected private keys %x, %x, to be be different despite db persistence if force generate", keyManager0.PrivateKey(), keyManager1.PrivateKey()) + } +} + +// cursor errors +func TestCursorErrors(t *testing.T) { + memdb, _ := ethdb.NewMemDatabase() + keyManager0 := NewDBKeyManager(memdb) + err := keyManager0.Init("", 0, false) + err = keyManager0.Init("", 1, false) + if err == nil { + t.Error("Expected cursor error") + } + err = keyManager0.SetCursor(1) + if err == nil { + t.Error("Expected cursor error") + } +} + +func TestExportImport(t *testing.T) { + memdb, _ := ethdb.NewMemDatabase() + keyManager0 := NewDBKeyManager(memdb) + err := keyManager0.Init("", 0, false) + basedir0 := "/tmp/ethtest0" + os.RemoveAll(basedir0) + os.Mkdir(basedir0, 0777) + keyManager0.Export(basedir0) + + keyManager1 := NewFileKeyManager(basedir0) + err = keyManager1.Init("", 0, false) + if err != nil { + t.Error("Unexpected error: ", err) + } + fmt.Printf("keyRing: %v\n", keyManager0.KeyPair()) + fmt.Printf("keyRing: %v\n", keyManager1.KeyPair()) + if string(keyManager0.PrivateKey()) != string(keyManager1.PrivateKey()) { + t.Error("Expected private keys %x, %x, to be identical via export to filestore basedir", keyManager0.PrivateKey(), keyManager1.PrivateKey()) + } + path.Join("") + + // memdb, _ = ethdb.NewMemDatabase() + // keyManager2 := NewDBKeyManager(memdb) + // err = keyManager2.InitFromSecretsFile("", 0, path.Join(basedir0, "default.prv")) + // if err != nil { + // t.Error("Unexpected error: ", err) + // } + // if string(keyManager0.PrivateKey()) != string(keyManager2.PrivateKey()) { + // t.Error("Expected private keys %s, %s, to be identical via export/import prv", keyManager0.PrivateKey(), keyManager1.PrivateKey()) + // } + + // memdb, _ = ethdb.NewMemDatabase() + // keyManager3 := NewDBKeyManager(memdb) + // err = keyManager3.InitFromSecretsFile("", 0, path.Join(basedir0, "default.mne")) + // if err != nil { + // t.Error("Unexpected error: ", err) + // } + // if string(keyManager0.PrivateKey()) != string(keyManager3.PrivateKey()) { + // t.Error("Expected private keys %s, %s, to be identical via export/import mnemonic file", keyManager0.PrivateKey(), keyManager1.PrivateKey()) + // } +} diff --git a/ethcrypto/mnemonic.go b/ethcrypto/mnemonic.go new file mode 100644 index 000000000..6134f85f7 --- /dev/null +++ b/ethcrypto/mnemonic.go @@ -0,0 +1,76 @@ +package ethcrypto + +import ( + "fmt" + "io/ioutil" + "path" + "runtime" + "strconv" + "strings" +) + +func InitWords() []string { + _, thisfile, _, _ := runtime.Caller(1) + filename := path.Join(path.Dir(thisfile), "mnemonic.words.lst") + content, err := ioutil.ReadFile(filename) + if err != nil { + panic(fmt.Errorf("reading mnemonic word list file 'mnemonic.words.lst' failed: ", err)) + } + return strings.Split(string(content), "\n") +} + +var words = InitWords() + +// TODO: See if we can refactor this into a shared util lib if we need it multiple times +func IndexOf(slice []string, value string) int64 { + for p, v := range slice { + if v == value { + return int64(p) + } + } + return -1 +} + +func MnemonicEncode(message string) []string { + var out []string + n := int64(len(words)) + + for i := 0; i < len(message); i += (len(message) / 8) { + x := message[i : i+8] + bit, _ := strconv.ParseInt(x, 16, 64) + w1 := (bit % n) + w2 := ((bit / n) + w1) % n + w3 := ((bit / n / n) + w2) % n + out = append(out, words[w1], words[w2], words[w3]) + } + return out +} + +func MnemonicDecode(wordsar []string) string { + var out string + n := int64(len(words)) + + for i := 0; i < len(wordsar); i += 3 { + word1 := wordsar[i] + word2 := wordsar[i+1] + word3 := wordsar[i+2] + w1 := IndexOf(words, word1) + w2 := IndexOf(words, word2) + w3 := IndexOf(words, word3) + + y := (w2 - w1) % n + z := (w3 - w2) % n + + // Golang handles modulo with negative numbers different then most languages + // The modulo can be negative, we don't want that. + if z < 0 { + z += n + } + if y < 0 { + y += n + } + x := w1 + n*(y) + n*n*(z) + out += fmt.Sprintf("%08x", x) + } + return out +} diff --git a/ethcrypto/mnemonic.words.lst b/ethcrypto/mnemonic.words.lst new file mode 100644 index 000000000..6bf412ce1 --- /dev/null +++ b/ethcrypto/mnemonic.words.lst @@ -0,0 +1,1626 @@ +like +just +love +know +never +want +time +out +there +make +look +eye +down +only +think +heart +back +then +into +about +more +away +still +them +take +thing +even +through +long +always +world +too +friend +tell +try +hand +thought +over +here +other +need +smile +again +much +cry +been +night +ever +little +said +end +some +those +around +mind +people +girl +leave +dream +left +turn +myself +give +nothing +really +off +before +something +find +walk +wish +good +once +place +ask +stop +keep +watch +seem +everything +wait +got +yet +made +remember +start +alone +run +hope +maybe +believe +body +hate +after +close +talk +stand +own +each +hurt +help +home +god +soul +new +many +two +inside +should +true +first +fear +mean +better +play +another +gone +change +use +wonder +someone +hair +cold +open +best +any +behind +happen +water +dark +laugh +stay +forever +name +work +show +sky +break +came +deep +door +put +black +together +upon +happy +such +great +white +matter +fill +past +please +burn +cause +enough +touch +moment +soon +voice +scream +anything +stare +sound +red +everyone +hide +kiss +truth +death +beautiful +mine +blood +broken +very +pass +next +forget +tree +wrong +air +mother +understand +lip +hit +wall +memory +sleep +free +high +realize +school +might +skin +sweet +perfect +blue +kill +breath +dance +against +fly +between +grow +strong +under +listen +bring +sometimes +speak +pull +person +become +family +begin +ground +real +small +father +sure +feet +rest +young +finally +land +across +today +different +guy +line +fire +reason +reach +second +slowly +write +eat +smell +mouth +step +learn +three +floor +promise +breathe +darkness +push +earth +guess +save +song +above +along +both +color +house +almost +sorry +anymore +brother +okay +dear +game +fade +already +apart +warm +beauty +heard +notice +question +shine +began +piece +whole +shadow +secret +street +within +finger +point +morning +whisper +child +moon +green +story +glass +kid +silence +since +soft +yourself +empty +shall +angel +answer +baby +bright +dad +path +worry +hour +drop +follow +power +war +half +flow +heaven +act +chance +fact +least +tired +children +near +quite +afraid +rise +sea +taste +window +cover +nice +trust +lot +sad +cool +force +peace +return +blind +easy +ready +roll +rose +drive +held +music +beneath +hang +mom +paint +emotion +quiet +clear +cloud +few +pretty +bird +outside +paper +picture +front +rock +simple +anyone +meant +reality +road +sense +waste +bit +leaf +thank +happiness +meet +men +smoke +truly +decide +self +age +book +form +alive +carry +escape +damn +instead +able +ice +minute +throw +catch +leg +ring +course +goodbye +lead +poem +sick +corner +desire +known +problem +remind +shoulder +suppose +toward +wave +drink +jump +woman +pretend +sister +week +human +joy +crack +grey +pray +surprise +dry +knee +less +search +bleed +caught +clean +embrace +future +king +son +sorrow +chest +hug +remain +sat +worth +blow +daddy +final +parent +tight +also +create +lonely +safe +cross +dress +evil +silent +bone +fate +perhaps +anger +class +scar +snow +tiny +tonight +continue +control +dog +edge +mirror +month +suddenly +comfort +given +loud +quickly +gaze +plan +rush +stone +town +battle +ignore +spirit +stood +stupid +yours +brown +build +dust +hey +kept +pay +phone +twist +although +ball +beyond +hidden +nose +taken +fail +float +pure +somehow +wash +wrap +angry +cheek +creature +forgotten +heat +rip +single +space +special +weak +whatever +yell +anyway +blame +job +choose +country +curse +drift +echo +figure +grew +laughter +neck +suffer +worse +yeah +disappear +foot +forward +knife +mess +somewhere +stomach +storm +beg +idea +lift +offer +breeze +field +five +often +simply +stuck +win +allow +confuse +enjoy +except +flower +seek +strength +calm +grin +gun +heavy +hill +large +ocean +shoe +sigh +straight +summer +tongue +accept +crazy +everyday +exist +grass +mistake +sent +shut +surround +table +ache +brain +destroy +heal +nature +shout +sign +stain +choice +doubt +glance +glow +mountain +queen +stranger +throat +tomorrow +city +either +fish +flame +rather +shape +spin +spread +ash +distance +finish +image +imagine +important +nobody +shatter +warmth +became +feed +flesh +funny +lust +shirt +trouble +yellow +attention +bare +bite +money +protect +amaze +appear +born +choke +completely +daughter +fresh +friendship +gentle +probably +six +deserve +expect +grab +middle +nightmare +river +thousand +weight +worst +wound +barely +bottle +cream +regret +relationship +stick +test +crush +endless +fault +itself +rule +spill +art +circle +join +kick +mask +master +passion +quick +raise +smooth +unless +wander +actually +broke +chair +deal +favorite +gift +note +number +sweat +box +chill +clothes +lady +mark +park +poor +sadness +tie +animal +belong +brush +consume +dawn +forest +innocent +pen +pride +stream +thick +clay +complete +count +draw +faith +press +silver +struggle +surface +taught +teach +wet +bless +chase +climb +enter +letter +melt +metal +movie +stretch +swing +vision +wife +beside +crash +forgot +guide +haunt +joke +knock +plant +pour +prove +reveal +steal +stuff +trip +wood +wrist +bother +bottom +crawl +crowd +fix +forgive +frown +grace +loose +lucky +party +release +surely +survive +teacher +gently +grip +speed +suicide +travel +treat +vein +written +cage +chain +conversation +date +enemy +however +interest +million +page +pink +proud +sway +themselves +winter +church +cruel +cup +demon +experience +freedom +pair +pop +purpose +respect +shoot +softly +state +strange +bar +birth +curl +dirt +excuse +lord +lovely +monster +order +pack +pants +pool +scene +seven +shame +slide +ugly +among +blade +blonde +closet +creek +deny +drug +eternity +gain +grade +handle +key +linger +pale +prepare +swallow +swim +tremble +wheel +won +cast +cigarette +claim +college +direction +dirty +gather +ghost +hundred +loss +lung +orange +present +swear +swirl +twice +wild +bitter +blanket +doctor +everywhere +flash +grown +knowledge +numb +pressure +radio +repeat +ruin +spend +unknown +buy +clock +devil +early +false +fantasy +pound +precious +refuse +sheet +teeth +welcome +add +ahead +block +bury +caress +content +depth +despite +distant +marry +purple +threw +whenever +bomb +dull +easily +grasp +hospital +innocence +normal +receive +reply +rhyme +shade +someday +sword +toe +visit +asleep +bought +center +consider +flat +hero +history +ink +insane +muscle +mystery +pocket +reflection +shove +silently +smart +soldier +spot +stress +train +type +view +whether +bus +energy +explain +holy +hunger +inch +magic +mix +noise +nowhere +prayer +presence +shock +snap +spider +study +thunder +trail +admit +agree +bag +bang +bound +butterfly +cute +exactly +explode +familiar +fold +further +pierce +reflect +scent +selfish +sharp +sink +spring +stumble +universe +weep +women +wonderful +action +ancient +attempt +avoid +birthday +branch +chocolate +core +depress +drunk +especially +focus +fruit +honest +match +palm +perfectly +pillow +pity +poison +roar +shift +slightly +thump +truck +tune +twenty +unable +wipe +wrote +coat +constant +dinner +drove +egg +eternal +flight +flood +frame +freak +gasp +glad +hollow +motion +peer +plastic +root +screen +season +sting +strike +team +unlike +victim +volume +warn +weird +attack +await +awake +built +charm +crave +despair +fought +grant +grief +horse +limit +message +ripple +sanity +scatter +serve +split +string +trick +annoy +blur +boat +brave +clearly +cling +connect +fist +forth +imagination +iron +jock +judge +lesson +milk +misery +nail +naked +ourselves +poet +possible +princess +sail +size +snake +society +stroke +torture +toss +trace +wise +bloom +bullet +cell +check +cost +darling +during +footstep +fragile +hallway +hardly +horizon +invisible +journey +midnight +mud +nod +pause +relax +shiver +sudden +value +youth +abuse +admire +blink +breast +bruise +constantly +couple +creep +curve +difference +dumb +emptiness +gotta +honor +plain +planet +recall +rub +ship +slam +soar +somebody +tightly +weather +adore +approach +bond +bread +burst +candle +coffee +cousin +crime +desert +flutter +frozen +grand +heel +hello +language +level +movement +pleasure +powerful +random +rhythm +settle +silly +slap +sort +spoken +steel +threaten +tumble +upset +aside +awkward +bee +blank +board +button +card +carefully +complain +crap +deeply +discover +drag +dread +effort +entire +fairy +giant +gotten +greet +illusion +jeans +leap +liquid +march +mend +nervous +nine +replace +rope +spine +stole +terror +accident +apple +balance +boom +childhood +collect +demand +depression +eventually +faint +glare +goal +group +honey +kitchen +laid +limb +machine +mere +mold +murder +nerve +painful +poetry +prince +rabbit +shelter +shore +shower +soothe +stair +steady +sunlight +tangle +tease +treasure +uncle +begun +bliss +canvas +cheer +claw +clutch +commit +crimson +crystal +delight +doll +existence +express +fog +football +gay +goose +guard +hatred +illuminate +mass +math +mourn +rich +rough +skip +stir +student +style +support +thorn +tough +yard +yearn +yesterday +advice +appreciate +autumn +bank +beam +bowl +capture +carve +collapse +confusion +creation +dove +feather +girlfriend +glory +government +harsh +hop +inner +loser +moonlight +neighbor +neither +peach +pig +praise +screw +shield +shimmer +sneak +stab +subject +throughout +thrown +tower +twirl +wow +army +arrive +bathroom +bump +cease +cookie +couch +courage +dim +guilt +howl +hum +husband +insult +led +lunch +mock +mostly +natural +nearly +needle +nerd +peaceful +perfection +pile +price +remove +roam +sanctuary +serious +shiny +shook +sob +stolen +tap +vain +void +warrior +wrinkle +affection +apologize +blossom +bounce +bridge +cheap +crumble +decision +descend +desperately +dig +dot +flip +frighten +heartbeat +huge +lazy +lick +odd +opinion +process +puzzle +quietly +retreat +score +sentence +separate +situation +skill +soak +square +stray +taint +task +tide +underneath +veil +whistle +anywhere +bedroom +bid +bloody +burden +careful +compare +concern +curtain +decay +defeat +describe +double +dreamer +driver +dwell +evening +flare +flicker +grandma +guitar +harm +horrible +hungry +indeed +lace +melody +monkey +nation +object +obviously +rainbow +salt +scratch +shown +shy +stage +stun +third +tickle +useless +weakness +worship +worthless +afternoon +beard +boyfriend +bubble +busy +certain +chin +concrete +desk +diamond +doom +drawn +due +felicity +freeze +frost +garden +glide +harmony +hopefully +hunt +jealous +lightning +mama +mercy +peel +physical +position +pulse +punch +quit +rant +respond +salty +sane +satisfy +savior +sheep +slept +social +sport +tuck +utter +valley +wolf +aim +alas +alter +arrow +awaken +beaten +belief +brand +ceiling +cheese +clue +confidence +connection +daily +disguise +eager +erase +essence +everytime +expression +fan +flag +flirt +foul +fur +giggle +glorious +ignorance +law +lifeless +measure +mighty +muse +north +opposite +paradise +patience +patient +pencil +petal +plate +ponder +possibly +practice +slice +spell +stock +strife +strip +suffocate +suit +tender +tool +trade +velvet +verse +waist +witch +aunt +bench +bold +cap +certainly +click +companion +creator +dart +delicate +determine +dish +dragon +drama +drum +dude +everybody +feast +forehead +former +fright +fully +gas +hook +hurl +invite +juice +manage +moral +possess +raw +rebel +royal +scale +scary +several +slight +stubborn +swell +talent +tea +terrible +thread +torment +trickle +usually +vast +violence +weave +acid +agony +ashamed +awe +belly +blend +blush +character +cheat +common +company +coward +creak +danger +deadly +defense +define +depend +desperate +destination +dew +duck +dusty +embarrass +engine +example +explore +foe +freely +frustrate +generation +glove +guilty +health +hurry +idiot +impossible +inhale +jaw +kingdom +mention +mist +moan +mumble +mutter +observe +ode +pathetic +pattern +pie +prefer +puff +rape +rare +revenge +rude +scrape +spiral +squeeze +strain +sunset +suspend +sympathy +thigh +throne +total +unseen +weapon +weary \ No newline at end of file diff --git a/ethutil/mnemonic_test.go b/ethcrypto/mnemonic_test.go similarity index 98% rename from ethutil/mnemonic_test.go rename to ethcrypto/mnemonic_test.go index ccf3f9883..8bd8859ae 100644 --- a/ethutil/mnemonic_test.go +++ b/ethcrypto/mnemonic_test.go @@ -1,4 +1,4 @@ -package ethutil +package ethcrypto import ( "testing" diff --git a/ethereum.go b/ethereum.go index a3df23e92..b78b0658f 100644 --- a/ethereum.go +++ b/ethereum.go @@ -4,7 +4,7 @@ import ( "container/list" "fmt" "github.com/ethereum/eth-go/ethchain" - "github.com/ethereum/eth-go/ethdb" + "github.com/ethereum/eth-go/ethcrypto" "github.com/ethereum/eth-go/ethlog" "github.com/ethereum/eth-go/ethrpc" "github.com/ethereum/eth-go/ethutil" @@ -74,16 +74,15 @@ type Ethereum struct { reactor *ethutil.ReactorEngine RpcServer *ethrpc.JsonRpcServer + + keyManager *ethcrypto.KeyManager } -func New(caps Caps, usePnp bool) (*Ethereum, error) { - db, err := ethdb.NewLDBDatabase("database") - //db, err := ethdb.NewMemDatabase() - if err != nil { - return nil, err - } +func New(db ethutil.Database, keyManager *ethcrypto.KeyManager, caps Caps, usePnp bool) (*Ethereum, error) { + var err error var nat NAT + if usePnp { nat, err = Discover() if err != nil { @@ -102,6 +101,7 @@ func New(caps Caps, usePnp bool) (*Ethereum, error) { Nonce: nonce, serverCaps: caps, nat: nat, + keyManager: keyManager, } ethereum.reactor = ethutil.NewReactorEngine() @@ -119,6 +119,10 @@ func (s *Ethereum) Reactor() *ethutil.ReactorEngine { return s.reactor } +func (s *Ethereum) KeyManager() *ethcrypto.KeyManager { + return s.keyManager +} + func (s *Ethereum) BlockChain() *ethchain.BlockChain { return s.blockChain } diff --git a/ethpub/pub.go b/ethpub/pub.go index 250ba71f3..ee4140899 100644 --- a/ethpub/pub.go +++ b/ethpub/pub.go @@ -2,9 +2,9 @@ package ethpub import ( "bytes" - "encoding/hex" "encoding/json" "github.com/ethereum/eth-go/ethchain" + "github.com/ethereum/eth-go/ethcrypto" "github.com/ethereum/eth-go/ethlog" "github.com/ethereum/eth-go/ethutil" "math/big" @@ -19,6 +19,7 @@ type PEthereum struct { stateManager *ethchain.StateManager blockChain *ethchain.BlockChain txPool *ethchain.TxPool + keyManager *ethcrypto.KeyManager } func NewPEthereum(manager ethchain.EthManager) *PEthereum { @@ -27,24 +28,23 @@ func NewPEthereum(manager ethchain.EthManager) *PEthereum { manager.StateManager(), manager.BlockChain(), manager.TxPool(), + manager.KeyManager(), } } func (lib *PEthereum) GetBlock(hexHash string) *PBlock { - hash := ethutil.FromHex(hexHash) + hash := ethutil.Hex2Bytes(hexHash) block := lib.blockChain.GetBlock(hash) return NewPBlock(block) } func (lib *PEthereum) GetKey() *PKey { - keyPair := ethutil.GetKeyRing().Get(0) - - return NewPKey(keyPair) + return NewPKey(lib.keyManager.KeyPair()) } func (lib *PEthereum) GetStateObject(address string) *PStateObject { - stateObject := lib.stateManager.CurrentState().GetStateObject(ethutil.FromHex(address)) + stateObject := lib.stateManager.CurrentState().GetStateObject(ethutil.Hex2Bytes(address)) if stateObject != nil { return NewPStateObject(stateObject) } @@ -79,17 +79,13 @@ func (lib *PEthereum) GetIsListening() bool { } func (lib *PEthereum) GetCoinBase() string { - data, _ := ethutil.Config.Db.Get([]byte("KeyRing")) - keyRing := ethutil.NewValueFromBytes(data) - key := keyRing.Get(0).Bytes() - - return lib.SecretToAddress(hex.EncodeToString(key)) + return ethutil.Bytes2Hex(lib.keyManager.Address()) } func (lib *PEthereum) GetTransactionsFor(address string, asJson bool) interface{} { sBlk := lib.manager.BlockChain().LastBlockHash blk := lib.manager.BlockChain().GetBlock(sBlk) - addr := []byte(ethutil.FromHex(address)) + addr := []byte(ethutil.Hex2Bytes(address)) var txs []*PTx @@ -129,12 +125,12 @@ func (lib *PEthereum) IsContract(address string) bool { } func (lib *PEthereum) SecretToAddress(key string) string { - pair, err := ethutil.NewKeyPairFromSec(ethutil.FromHex(key)) + pair, err := ethcrypto.NewKeyPairFromSec(ethutil.Hex2Bytes(key)) if err != nil { return "" } - return ethutil.Hex(pair.Address()) + return ethutil.Bytes2Hex(pair.Address()) } func (lib *PEthereum) Transact(key, recipient, valueStr, gasStr, gasPriceStr, dataStr string) (*PReceipt, error) { @@ -145,7 +141,7 @@ func (lib *PEthereum) Create(key, valueStr, gasStr, gasPriceStr, script string) return lib.createTx(key, "", valueStr, gasStr, gasPriceStr, script) } -var namereg = ethutil.FromHex("bb5f186604d057c1c5240ca2ae0f6430138ac010") +var namereg = ethutil.Hex2Bytes("bb5f186604d057c1c5240ca2ae0f6430138ac010") func GetAddressFromNameReg(stateManager *ethchain.StateManager, name string) []byte { recp := new(big.Int).SetBytes([]byte(name)) @@ -169,16 +165,16 @@ func (lib *PEthereum) createTx(key, recipient, valueStr, gasStr, gasPriceStr, sc if len(addr) > 0 { hash = addr } else { - hash = ethutil.FromHex(recipient) + hash = ethutil.Hex2Bytes(recipient) } } - var keyPair *ethutil.KeyPair + var keyPair *ethcrypto.KeyPair var err error if key[0:2] == "0x" { - keyPair, err = ethutil.NewKeyPairFromSec([]byte(ethutil.FromHex(key[2:]))) + keyPair, err = ethcrypto.NewKeyPairFromSec([]byte(ethutil.Hex2Bytes(key[2:]))) } else { - keyPair, err = ethutil.NewKeyPairFromSec([]byte(ethutil.FromHex(key))) + keyPair, err = ethcrypto.NewKeyPairFromSec([]byte(ethutil.Hex2Bytes(key))) } if err != nil { @@ -194,7 +190,7 @@ func (lib *PEthereum) createTx(key, recipient, valueStr, gasStr, gasPriceStr, sc var script []byte var err error if ethutil.IsHex(scriptStr) { - script = ethutil.FromHex(scriptStr) + script = ethutil.Hex2Bytes(scriptStr[2:]) } else { script, err = ethutil.Compile(scriptStr) if err != nil { diff --git a/ethpub/types.go b/ethpub/types.go index 0ced68ad1..05031dea2 100644 --- a/ethpub/types.go +++ b/ethpub/types.go @@ -1,10 +1,10 @@ package ethpub import ( - "encoding/hex" "encoding/json" "fmt" "github.com/ethereum/eth-go/ethchain" + "github.com/ethereum/eth-go/ethcrypto" "github.com/ethereum/eth-go/ethutil" "strings" ) @@ -66,7 +66,7 @@ func NewPBlock(block *ethchain.Block) *PBlock { return nil } - return &PBlock{ref: block, Number: int(block.Number.Uint64()), GasUsed: block.GasUsed.String(), GasLimit: block.GasLimit.String(), Hash: ethutil.Hex(block.Hash()), Transactions: string(txJson), Time: block.Time, Coinbase: ethutil.Hex(block.Coinbase)} + return &PBlock{ref: block, Number: int(block.Number.Uint64()), GasUsed: block.GasUsed.String(), GasLimit: block.GasLimit.String(), Hash: ethutil.Bytes2Hex(block.Hash()), Transactions: string(txJson), Time: block.Time, Coinbase: ethutil.Bytes2Hex(block.Coinbase)} } func (self *PBlock) ToString() string { @@ -78,7 +78,7 @@ func (self *PBlock) ToString() string { } func (self *PBlock) GetTransaction(hash string) *PTx { - tx := self.ref.GetTransaction(ethutil.FromHex(hash)) + tx := self.ref.GetTransaction(ethutil.Hex2Bytes(hash)) if tx == nil { return nil } @@ -103,22 +103,22 @@ type PTx struct { } func NewPTx(tx *ethchain.Transaction) *PTx { - hash := hex.EncodeToString(tx.Hash()) - receiver := hex.EncodeToString(tx.Recipient) + hash := ethutil.Bytes2Hex(tx.Hash()) + receiver := ethutil.Bytes2Hex(tx.Recipient) if receiver == "0000000000000000000000000000000000000000" { - receiver = hex.EncodeToString(tx.CreationAddress()) + receiver = ethutil.Bytes2Hex(tx.CreationAddress()) } - sender := hex.EncodeToString(tx.Sender()) + sender := ethutil.Bytes2Hex(tx.Sender()) createsContract := tx.CreatesContract() var data string if tx.CreatesContract() { data = strings.Join(ethchain.Disassemble(tx.Data), "\n") } else { - data = hex.EncodeToString(tx.Data) + data = ethutil.Bytes2Hex(tx.Data) } - return &PTx{ref: tx, Hash: hash, Value: ethutil.CurrencyToString(tx.Value), Address: receiver, Contract: tx.CreatesContract(), Gas: tx.Gas.String(), GasPrice: tx.GasPrice.String(), Data: data, Sender: sender, CreatesContract: createsContract, RawData: hex.EncodeToString(tx.Data)} + return &PTx{ref: tx, Hash: hash, Value: ethutil.CurrencyToString(tx.Value), Address: receiver, Contract: tx.CreatesContract(), Gas: tx.Gas.String(), GasPrice: tx.GasPrice.String(), Data: data, Sender: sender, CreatesContract: createsContract, RawData: ethutil.Bytes2Hex(tx.Data)} } func (self *PTx) ToString() string { @@ -131,8 +131,8 @@ type PKey struct { PublicKey string `json:"publicKey"` } -func NewPKey(key *ethutil.KeyPair) *PKey { - return &PKey{ethutil.Hex(key.Address()), ethutil.Hex(key.PrivateKey), ethutil.Hex(key.PublicKey)} +func NewPKey(key *ethcrypto.KeyPair) *PKey { + return &PKey{ethutil.Bytes2Hex(key.Address()), ethutil.Bytes2Hex(key.PrivateKey), ethutil.Bytes2Hex(key.PublicKey)} } type PReceipt struct { @@ -145,9 +145,9 @@ type PReceipt struct { func NewPReciept(contractCreation bool, creationAddress, hash, address []byte) *PReceipt { return &PReceipt{ contractCreation, - ethutil.Hex(creationAddress), - ethutil.Hex(hash), - ethutil.Hex(address), + ethutil.Bytes2Hex(creationAddress), + ethutil.Bytes2Hex(hash), + ethutil.Bytes2Hex(address), } } @@ -182,7 +182,7 @@ func (c *PStateObject) Value() string { func (c *PStateObject) Address() string { if c.object != nil { - return ethutil.Hex(c.object.Address()) + return ethutil.Bytes2Hex(c.object.Address()) } return "" @@ -198,7 +198,7 @@ func (c *PStateObject) Nonce() int { func (c *PStateObject) Root() string { if c.object != nil { - return ethutil.Hex(ethutil.NewValue(c.object.State().Root()).Bytes()) + return ethutil.Bytes2Hex(ethutil.NewValue(c.object.State().Root()).Bytes()) } return "" @@ -221,7 +221,7 @@ func (c *PStateObject) StateKeyVal(asJson bool) interface{} { var values []KeyVal if c.object != nil { c.object.State().EachStorage(func(name string, value *ethutil.Value) { - values = append(values, KeyVal{name, ethutil.Hex(value.Bytes())}) + values = append(values, KeyVal{name, ethutil.Bytes2Hex(value.Bytes())}) }) } @@ -247,7 +247,7 @@ func (c *PStateObject) Script() string { func (c *PStateObject) HexScript() string { if c.object != nil { - return ethutil.Hex(c.object.Script()) + return ethutil.Bytes2Hex(c.object.Script()) } return "" @@ -260,5 +260,5 @@ type PStorageState struct { } func NewPStorageState(storageObject *ethchain.StorageState) *PStorageState { - return &PStorageState{ethutil.Hex(storageObject.StateAddress), ethutil.Hex(storageObject.Address), storageObject.Value.String()} + return &PStorageState{ethutil.Bytes2Hex(storageObject.StateAddress), ethutil.Bytes2Hex(storageObject.Address), storageObject.Value.String()} } diff --git a/ethrpc/packages.go b/ethrpc/packages.go index 710275780..0662f0edd 100644 --- a/ethrpc/packages.go +++ b/ethrpc/packages.go @@ -182,7 +182,7 @@ func (p *EthereumApi) GetStorageAt(args *GetStorageArgs, reply *string) error { } else { // Convert the incoming string (which is a bigint) into hex i, _ := new(big.Int).SetString(args.Key, 10) - hx = ethutil.Hex(i.Bytes()) + hx = ethutil.Bytes2Hex(i.Bytes()) } logger.Debugf("GetStorageAt(%s, %s)\n", args.Address, hx) value := state.GetStorage(hx) diff --git a/ethutil/encoding.go b/ethtrie/encoding.go similarity index 98% rename from ethutil/encoding.go rename to ethtrie/encoding.go index 9fcdf3edf..c9c391110 100644 --- a/ethutil/encoding.go +++ b/ethtrie/encoding.go @@ -1,4 +1,4 @@ -package ethutil +package ethtrie import ( "bytes" diff --git a/ethutil/encoding_test.go b/ethtrie/encoding_test.go similarity index 99% rename from ethutil/encoding_test.go rename to ethtrie/encoding_test.go index 10e1995c0..7a4849678 100644 --- a/ethutil/encoding_test.go +++ b/ethtrie/encoding_test.go @@ -1,4 +1,4 @@ -package ethutil +package ethtrie import ( "fmt" diff --git a/ethtrie/slice.go b/ethtrie/slice.go new file mode 100644 index 000000000..b9d5d1285 --- /dev/null +++ b/ethtrie/slice.go @@ -0,0 +1,26 @@ +package ethtrie + +import () + +// Helper function for comparing slices +func CompareIntSlice(a, b []int) bool { + if len(a) != len(b) { + return false + } + for i, v := range a { + if v != b[i] { + return false + } + } + return true +} + +// Returns the amount of nibbles that match each other from 0 ... +func MatchingNibbleLength(a, b []int) int { + i := 0 + for CompareIntSlice(a[:i+1], b[:i+1]) && i < len(b) { + i += 1 + } + + return i +} diff --git a/ethutil/trie.go b/ethtrie/trie.go similarity index 91% rename from ethutil/trie.go rename to ethtrie/trie.go index 56f1648a6..6a5d3807c 100644 --- a/ethutil/trie.go +++ b/ethtrie/trie.go @@ -1,7 +1,9 @@ -package ethutil +package ethtrie import ( "fmt" + "github.com/ethereum/eth-go/ethcrypto" + "github.com/ethereum/eth-go/ethutil" "reflect" "sync" ) @@ -21,11 +23,11 @@ type StateObject interface { type Node struct { Key []byte - Value *Value + Value *ethutil.Value Dirty bool } -func NewNode(key []byte, val *Value, dirty bool) *Node { +func NewNode(key []byte, val *ethutil.Value, dirty bool) *Node { return &Node{Key: key, Value: val, Dirty: dirty} } @@ -35,20 +37,20 @@ func (n *Node) Copy() *Node { type Cache struct { nodes map[string]*Node - db Database + db ethutil.Database IsDirty bool } -func NewCache(db Database) *Cache { +func NewCache(db ethutil.Database) *Cache { return &Cache{db: db, nodes: make(map[string]*Node)} } func (cache *Cache) PutValue(v interface{}, force bool) interface{} { - value := NewValue(v) + value := ethutil.NewValue(v) enc := value.Encode() if len(enc) >= 32 || force { - sha := Sha3Bin(enc) + sha := ethcrypto.Sha3Bin(enc) cache.nodes[string(sha)] = NewNode(sha, value, true) cache.IsDirty = true @@ -63,7 +65,7 @@ func (cache *Cache) Put(v interface{}) interface{} { return cache.PutValue(v, false) } -func (cache *Cache) Get(key []byte) *Value { +func (cache *Cache) Get(key []byte) *ethutil.Value { // First check if the key is the cache if cache.nodes[string(key)] != nil { return cache.nodes[string(key)].Value @@ -72,7 +74,7 @@ func (cache *Cache) Get(key []byte) *Value { // Get the key of the database instead and cache it data, _ := cache.db.Get(key) // Create the cached value - value := NewValueFromBytes(data) + value := ethutil.NewValueFromBytes(data) // Create caching node cache.nodes[string(key)] = NewNode(key, value, false) @@ -132,7 +134,7 @@ type Trie struct { func copyRoot(root interface{}) interface{} { var prevRootCopy interface{} if b, ok := root.([]byte); ok { - prevRootCopy = CopyBytes(b) + prevRootCopy = ethutil.CopyBytes(b) } else { prevRootCopy = root } @@ -140,7 +142,7 @@ func copyRoot(root interface{}) interface{} { return prevRootCopy } -func NewTrie(db Database, Root interface{}) *Trie { +func NewTrie(db ethutil.Database, Root interface{}) *Trie { // Make absolute sure the root is copied r := copyRoot(Root) p := copyRoot(Root) @@ -188,7 +190,7 @@ func (t *Trie) Get(key string) string { defer t.mut.RUnlock() k := CompactHexDecode(key) - c := NewValue(t.GetState(t.Root, k)) + c := ethutil.NewValue(t.GetState(t.Root, k)) return c.Str() } @@ -211,7 +213,7 @@ func (t *Trie) Delete(key string) { } func (t *Trie) GetState(node interface{}, key []int) interface{} { - n := NewValue(node) + n := ethutil.NewValue(node) // Return the node if key is empty (= found) if len(key) == 0 || n.IsNil() || n.Len() == 0 { return node @@ -241,8 +243,8 @@ func (t *Trie) GetState(node interface{}, key []int) interface{} { return "" } -func (t *Trie) GetNode(node interface{}) *Value { - n := NewValue(node) +func (t *Trie) GetNode(node interface{}) *ethutil.Value { + n := ethutil.NewValue(node) if !n.Get(0).IsNil() { return n @@ -252,7 +254,7 @@ func (t *Trie) GetNode(node interface{}) *Value { if len(str) == 0 { return n } else if len(str) < 32 { - return NewValueFromBytes([]byte(str)) + return ethutil.NewValueFromBytes([]byte(str)) } return t.cache.Get(n.Bytes()) @@ -290,7 +292,7 @@ func (t *Trie) InsertState(node interface{}, key []int, value interface{}) inter } // New node - n := NewValue(node) + n := ethutil.NewValue(node) if node == nil || (n.Type() == reflect.String && (n.Str() == "" || n.Get(0).IsNil())) || n.Len() == 0 { newNode := []interface{}{CompactEncode(key), value} @@ -362,7 +364,7 @@ func (t *Trie) DeleteState(node interface{}, key []int) interface{} { } // New node - n := NewValue(node) + n := ethutil.NewValue(node) if node == nil || (n.Type() == reflect.String && (n.Str() == "" || n.Get(0).IsNil())) || n.Len() == 0 { return "" } @@ -439,7 +441,7 @@ func (t *Trie) DeleteState(node interface{}, key []int) interface{} { // Simple compare function which creates a rlp value out of the evaluated objects func (t *Trie) Cmp(trie *Trie) bool { - return NewValue(t.Root).Cmp(NewValue(trie.Root)) + return ethutil.NewValue(t.Root).Cmp(ethutil.NewValue(trie.Root)) } // Returns a copy of this trie @@ -469,7 +471,7 @@ func (t *Trie) NewIterator() *TrieIterator { // Some time in the near future this will need refactoring :-) // XXX Note to self, IsSlice == inline node. Str == sha3 to node -func (it *TrieIterator) workNode(currentNode *Value) { +func (it *TrieIterator) workNode(currentNode *ethutil.Value) { if currentNode.Len() == 2 { k := CompactDecode(currentNode.Get(0).Str()) @@ -512,7 +514,7 @@ func (it *TrieIterator) Collect() [][]byte { return nil } - it.getNode(NewValue(it.trie.Root).Bytes()) + it.getNode(ethutil.NewValue(it.trie.Root).Bytes()) return it.shas } @@ -533,17 +535,17 @@ func (it *TrieIterator) Value() string { return "" } -type EachCallback func(key string, node *Value) +type EachCallback func(key string, node *ethutil.Value) func (it *TrieIterator) Each(cb EachCallback) { - it.fetchNode(nil, NewValue(it.trie.Root).Bytes(), cb) + it.fetchNode(nil, ethutil.NewValue(it.trie.Root).Bytes(), cb) } func (it *TrieIterator) fetchNode(key []int, node []byte, cb EachCallback) { it.iterateNode(key, it.trie.cache.Get(node), cb) } -func (it *TrieIterator) iterateNode(key []int, currentNode *Value, cb EachCallback) { +func (it *TrieIterator) iterateNode(key []int, currentNode *ethutil.Value, cb EachCallback) { if currentNode.Len() == 2 { k := CompactDecode(currentNode.Get(0).Str()) diff --git a/ethutil/trie_test.go b/ethtrie/trie_test.go similarity index 99% rename from ethutil/trie_test.go rename to ethtrie/trie_test.go index 01207dbc3..a3d4547d7 100644 --- a/ethutil/trie_test.go +++ b/ethtrie/trie_test.go @@ -1,4 +1,4 @@ -package ethutil +package ethtrie import ( "bytes" diff --git a/ethutil/bytes.go b/ethutil/bytes.go index 5e3ee4a6f..c2817946b 100644 --- a/ethutil/bytes.go +++ b/ethutil/bytes.go @@ -3,6 +3,7 @@ package ethutil import ( "bytes" "encoding/binary" + "encoding/hex" "fmt" "math/big" "strings" @@ -91,9 +92,18 @@ func IsHex(str string) bool { return l >= 4 && l%2 == 0 && str[0:2] == "0x" } +func Bytes2Hex(d []byte) string { + return hex.EncodeToString(d) +} + +func Hex2Bytes(str string) []byte { + h, _ := hex.DecodeString(str) + return h +} + func StringToByteFunc(str string, cb func(str string) []byte) (ret []byte) { if len(str) > 1 && str[0:2] == "0x" && !strings.Contains(str, "\n") { - ret = FromHex(str[2:]) + ret = Hex2Bytes(str[2:]) } else { ret = cb(str) } @@ -110,7 +120,7 @@ func FormatData(data string) []byte { if data[0:1] == "\"" && data[len(data)-1:] == "\"" { d.SetBytes([]byte(data[1 : len(data)-1])) } else if len(data) > 1 && data[:2] == "0x" { - d.SetBytes(FromHex(data[2:])) + d.SetBytes(Hex2Bytes(data[2:])) } else { d.SetString(data, 0) } diff --git a/ethutil/common.go b/ethutil/common.go index f63ba5d83..6d88a1ed2 100644 --- a/ethutil/common.go +++ b/ethutil/common.go @@ -52,10 +52,3 @@ var ( Big32 = big.NewInt(32) Big256 = big.NewInt(0xff) ) - -// Creates an ethereum address given the bytes and the nonce -func CreateAddress(b []byte, nonce *big.Int) []byte { - addrBytes := append(b, nonce.Bytes()...) - - return Sha3Bin(addrBytes)[12:] -} diff --git a/ethutil/config.go b/ethutil/config.go index 6ebb5e8cd..675175cdd 100644 --- a/ethutil/config.go +++ b/ethutil/config.go @@ -17,7 +17,6 @@ type config struct { Paranoia bool Ver string ClientString string - Pubkey []byte Identifier string conf *globalconf.GlobalConf diff --git a/ethutil/helpers.go b/ethutil/helpers.go deleted file mode 100644 index aa0f79a04..000000000 --- a/ethutil/helpers.go +++ /dev/null @@ -1,64 +0,0 @@ -package ethutil - -import ( - "code.google.com/p/go.crypto/ripemd160" - "crypto/sha256" - "encoding/hex" - "github.com/obscuren/sha3" - "strconv" -) - -func Uitoa(i uint32) string { - return strconv.FormatUint(uint64(i), 10) -} - -func Sha256Bin(data []byte) []byte { - hash := sha256.Sum256(data) - - return hash[:] -} - -func Ripemd160(data []byte) []byte { - ripemd := ripemd160.New() - ripemd.Write(data) - - return ripemd.Sum(nil) -} - -func Sha3Bin(data []byte) []byte { - d := sha3.NewKeccak256() - d.Write(data) - - return d.Sum(nil) -} - -// Helper function for comparing slices -func CompareIntSlice(a, b []int) bool { - if len(a) != len(b) { - return false - } - for i, v := range a { - if v != b[i] { - return false - } - } - return true -} - -// Returns the amount of nibbles that match each other from 0 ... -func MatchingNibbleLength(a, b []int) int { - i := 0 - for CompareIntSlice(a[:i+1], b[:i+1]) && i < len(b) { - i += 1 - } - - return i -} - -func Hex(d []byte) string { - return hex.EncodeToString(d) -} -func FromHex(str string) []byte { - h, _ := hex.DecodeString(str) - return h -} diff --git a/ethutil/keypair.go b/ethutil/keypair.go deleted file mode 100644 index 29fb1bac5..000000000 --- a/ethutil/keypair.go +++ /dev/null @@ -1,115 +0,0 @@ -package ethutil - -import ( - "github.com/obscuren/secp256k1-go" -) - -type KeyPair struct { - PrivateKey []byte - PublicKey []byte - - // The associated account - account *StateObject -} - -func GenerateNewKeyPair() (*KeyPair, error) { - _, prv := secp256k1.GenerateKeyPair() - - return NewKeyPairFromSec(prv) -} - -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 -} diff --git a/ethutil/mnemonic.go b/ethutil/mnemonic.go deleted file mode 100644 index 00f089e3b..000000000 --- a/ethutil/mnemonic.go +++ /dev/null @@ -1,1690 +0,0 @@ -package ethutil - -import ( - "fmt" - "strconv" -) - -// TODO: See if we can refactor this into a shared util lib if we need it multiple times -func IndexOf(slice []string, value string) int64 { - for p, v := range slice { - if v == value { - return int64(p) - } - } - return -1 -} - -func MnemonicEncode(message string) []string { - var out []string - n := int64(len(words)) - - for i := 0; i < len(message); i += (len(message) / 8) { - x := message[i : i+8] - bit, _ := strconv.ParseInt(x, 16, 64) - w1 := (bit % n) - w2 := ((bit / n) + w1) % n - w3 := ((bit / n / n) + w2) % n - out = append(out, words[w1], words[w2], words[w3]) - } - return out -} - -func MnemonicDecode(wordsar []string) string { - var out string - n := int64(len(words)) - - for i := 0; i < len(wordsar); i += 3 { - word1 := wordsar[i] - word2 := wordsar[i+1] - word3 := wordsar[i+2] - w1 := IndexOf(words, word1) - w2 := IndexOf(words, word2) - w3 := IndexOf(words, word3) - - y := (w2 - w1) % n - z := (w3 - w2) % n - - // Golang handles modulo with negative numbers different then most languages - // The modulo can be negative, we don't want that. - if z < 0 { - z += n - } - if y < 0 { - y += n - } - x := w1 + n*(y) + n*n*(z) - out += fmt.Sprintf("%08x", x) - } - return out -} - -// Electrum word list -var words []string = []string{ - "like", - "just", - "love", - "know", - "never", - "want", - "time", - "out", - "there", - "make", - "look", - "eye", - "down", - "only", - "think", - "heart", - "back", - "then", - "into", - "about", - "more", - "away", - "still", - "them", - "take", - "thing", - "even", - "through", - "long", - "always", - "world", - "too", - "friend", - "tell", - "try", - "hand", - "thought", - "over", - "here", - "other", - "need", - "smile", - "again", - "much", - "cry", - "been", - "night", - "ever", - "little", - "said", - "end", - "some", - "those", - "around", - "mind", - "people", - "girl", - "leave", - "dream", - "left", - "turn", - "myself", - "give", - "nothing", - "really", - "off", - "before", - "something", - "find", - "walk", - "wish", - "good", - "once", - "place", - "ask", - "stop", - "keep", - "watch", - "seem", - "everything", - "wait", - "got", - "yet", - "made", - "remember", - "start", - "alone", - "run", - "hope", - "maybe", - "believe", - "body", - "hate", - "after", - "close", - "talk", - "stand", - "own", - "each", - "hurt", - "help", - "home", - "god", - "soul", - "new", - "many", - "two", - "inside", - "should", - "true", - "first", - "fear", - "mean", - "better", - "play", - "another", - "gone", - "change", - "use", - "wonder", - "someone", - "hair", - "cold", - "open", - "best", - "any", - "behind", - "happen", - "water", - "dark", - "laugh", - "stay", - "forever", - "name", - "work", - "show", - "sky", - "break", - "came", - "deep", - "door", - "put", - "black", - "together", - "upon", - "happy", - "such", - "great", - "white", - "matter", - "fill", - "past", - "please", - "burn", - "cause", - "enough", - "touch", - "moment", - "soon", - "voice", - "scream", - "anything", - "stare", - "sound", - "red", - "everyone", - "hide", - "kiss", - "truth", - "death", - "beautiful", - "mine", - "blood", - "broken", - "very", - "pass", - "next", - "forget", - "tree", - "wrong", - "air", - "mother", - "understand", - "lip", - "hit", - "wall", - "memory", - "sleep", - "free", - "high", - "realize", - "school", - "might", - "skin", - "sweet", - "perfect", - "blue", - "kill", - "breath", - "dance", - "against", - "fly", - "between", - "grow", - "strong", - "under", - "listen", - "bring", - "sometimes", - "speak", - "pull", - "person", - "become", - "family", - "begin", - "ground", - "real", - "small", - "father", - "sure", - "feet", - "rest", - "young", - "finally", - "land", - "across", - "today", - "different", - "guy", - "line", - "fire", - "reason", - "reach", - "second", - "slowly", - "write", - "eat", - "smell", - "mouth", - "step", - "learn", - "three", - "floor", - "promise", - "breathe", - "darkness", - "push", - "earth", - "guess", - "save", - "song", - "above", - "along", - "both", - "color", - "house", - "almost", - "sorry", - "anymore", - "brother", - "okay", - "dear", - "game", - "fade", - "already", - "apart", - "warm", - "beauty", - "heard", - "notice", - "question", - "shine", - "began", - "piece", - "whole", - "shadow", - "secret", - "street", - "within", - "finger", - "point", - "morning", - "whisper", - "child", - "moon", - "green", - "story", - "glass", - "kid", - "silence", - "since", - "soft", - "yourself", - "empty", - "shall", - "angel", - "answer", - "baby", - "bright", - "dad", - "path", - "worry", - "hour", - "drop", - "follow", - "power", - "war", - "half", - "flow", - "heaven", - "act", - "chance", - "fact", - "least", - "tired", - "children", - "near", - "quite", - "afraid", - "rise", - "sea", - "taste", - "window", - "cover", - "nice", - "trust", - "lot", - "sad", - "cool", - "force", - "peace", - "return", - "blind", - "easy", - "ready", - "roll", - "rose", - "drive", - "held", - "music", - "beneath", - "hang", - "mom", - "paint", - "emotion", - "quiet", - "clear", - "cloud", - "few", - "pretty", - "bird", - "outside", - "paper", - "picture", - "front", - "rock", - "simple", - "anyone", - "meant", - "reality", - "road", - "sense", - "waste", - "bit", - "leaf", - "thank", - "happiness", - "meet", - "men", - "smoke", - "truly", - "decide", - "self", - "age", - "book", - "form", - "alive", - "carry", - "escape", - "damn", - "instead", - "able", - "ice", - "minute", - "throw", - "catch", - "leg", - "ring", - "course", - "goodbye", - "lead", - "poem", - "sick", - "corner", - "desire", - "known", - "problem", - "remind", - "shoulder", - "suppose", - "toward", - "wave", - "drink", - "jump", - "woman", - "pretend", - "sister", - "week", - "human", - "joy", - "crack", - "grey", - "pray", - "surprise", - "dry", - "knee", - "less", - "search", - "bleed", - "caught", - "clean", - "embrace", - "future", - "king", - "son", - "sorrow", - "chest", - "hug", - "remain", - "sat", - "worth", - "blow", - "daddy", - "final", - "parent", - "tight", - "also", - "create", - "lonely", - "safe", - "cross", - "dress", - "evil", - "silent", - "bone", - "fate", - "perhaps", - "anger", - "class", - "scar", - "snow", - "tiny", - "tonight", - "continue", - "control", - "dog", - "edge", - "mirror", - "month", - "suddenly", - "comfort", - "given", - "loud", - "quickly", - "gaze", - "plan", - "rush", - "stone", - "town", - "battle", - "ignore", - "spirit", - "stood", - "stupid", - "yours", - "brown", - "build", - "dust", - "hey", - "kept", - "pay", - "phone", - "twist", - "although", - "ball", - "beyond", - "hidden", - "nose", - "taken", - "fail", - "float", - "pure", - "somehow", - "wash", - "wrap", - "angry", - "cheek", - "creature", - "forgotten", - "heat", - "rip", - "single", - "space", - "special", - "weak", - "whatever", - "yell", - "anyway", - "blame", - "job", - "choose", - "country", - "curse", - "drift", - "echo", - "figure", - "grew", - "laughter", - "neck", - "suffer", - "worse", - "yeah", - "disappear", - "foot", - "forward", - "knife", - "mess", - "somewhere", - "stomach", - "storm", - "beg", - "idea", - "lift", - "offer", - "breeze", - "field", - "five", - "often", - "simply", - "stuck", - "win", - "allow", - "confuse", - "enjoy", - "except", - "flower", - "seek", - "strength", - "calm", - "grin", - "gun", - "heavy", - "hill", - "large", - "ocean", - "shoe", - "sigh", - "straight", - "summer", - "tongue", - "accept", - "crazy", - "everyday", - "exist", - "grass", - "mistake", - "sent", - "shut", - "surround", - "table", - "ache", - "brain", - "destroy", - "heal", - "nature", - "shout", - "sign", - "stain", - "choice", - "doubt", - "glance", - "glow", - "mountain", - "queen", - "stranger", - "throat", - "tomorrow", - "city", - "either", - "fish", - "flame", - "rather", - "shape", - "spin", - "spread", - "ash", - "distance", - "finish", - "image", - "imagine", - "important", - "nobody", - "shatter", - "warmth", - "became", - "feed", - "flesh", - "funny", - "lust", - "shirt", - "trouble", - "yellow", - "attention", - "bare", - "bite", - "money", - "protect", - "amaze", - "appear", - "born", - "choke", - "completely", - "daughter", - "fresh", - "friendship", - "gentle", - "probably", - "six", - "deserve", - "expect", - "grab", - "middle", - "nightmare", - "river", - "thousand", - "weight", - "worst", - "wound", - "barely", - "bottle", - "cream", - "regret", - "relationship", - "stick", - "test", - "crush", - "endless", - "fault", - "itself", - "rule", - "spill", - "art", - "circle", - "join", - "kick", - "mask", - "master", - "passion", - "quick", - "raise", - "smooth", - "unless", - "wander", - "actually", - "broke", - "chair", - "deal", - "favorite", - "gift", - "note", - "number", - "sweat", - "box", - "chill", - "clothes", - "lady", - "mark", - "park", - "poor", - "sadness", - "tie", - "animal", - "belong", - "brush", - "consume", - "dawn", - "forest", - "innocent", - "pen", - "pride", - "stream", - "thick", - "clay", - "complete", - "count", - "draw", - "faith", - "press", - "silver", - "struggle", - "surface", - "taught", - "teach", - "wet", - "bless", - "chase", - "climb", - "enter", - "letter", - "melt", - "metal", - "movie", - "stretch", - "swing", - "vision", - "wife", - "beside", - "crash", - "forgot", - "guide", - "haunt", - "joke", - "knock", - "plant", - "pour", - "prove", - "reveal", - "steal", - "stuff", - "trip", - "wood", - "wrist", - "bother", - "bottom", - "crawl", - "crowd", - "fix", - "forgive", - "frown", - "grace", - "loose", - "lucky", - "party", - "release", - "surely", - "survive", - "teacher", - "gently", - "grip", - "speed", - "suicide", - "travel", - "treat", - "vein", - "written", - "cage", - "chain", - "conversation", - "date", - "enemy", - "however", - "interest", - "million", - "page", - "pink", - "proud", - "sway", - "themselves", - "winter", - "church", - "cruel", - "cup", - "demon", - "experience", - "freedom", - "pair", - "pop", - "purpose", - "respect", - "shoot", - "softly", - "state", - "strange", - "bar", - "birth", - "curl", - "dirt", - "excuse", - "lord", - "lovely", - "monster", - "order", - "pack", - "pants", - "pool", - "scene", - "seven", - "shame", - "slide", - "ugly", - "among", - "blade", - "blonde", - "closet", - "creek", - "deny", - "drug", - "eternity", - "gain", - "grade", - "handle", - "key", - "linger", - "pale", - "prepare", - "swallow", - "swim", - "tremble", - "wheel", - "won", - "cast", - "cigarette", - "claim", - "college", - "direction", - "dirty", - "gather", - "ghost", - "hundred", - "loss", - "lung", - "orange", - "present", - "swear", - "swirl", - "twice", - "wild", - "bitter", - "blanket", - "doctor", - "everywhere", - "flash", - "grown", - "knowledge", - "numb", - "pressure", - "radio", - "repeat", - "ruin", - "spend", - "unknown", - "buy", - "clock", - "devil", - "early", - "false", - "fantasy", - "pound", - "precious", - "refuse", - "sheet", - "teeth", - "welcome", - "add", - "ahead", - "block", - "bury", - "caress", - "content", - "depth", - "despite", - "distant", - "marry", - "purple", - "threw", - "whenever", - "bomb", - "dull", - "easily", - "grasp", - "hospital", - "innocence", - "normal", - "receive", - "reply", - "rhyme", - "shade", - "someday", - "sword", - "toe", - "visit", - "asleep", - "bought", - "center", - "consider", - "flat", - "hero", - "history", - "ink", - "insane", - "muscle", - "mystery", - "pocket", - "reflection", - "shove", - "silently", - "smart", - "soldier", - "spot", - "stress", - "train", - "type", - "view", - "whether", - "bus", - "energy", - "explain", - "holy", - "hunger", - "inch", - "magic", - "mix", - "noise", - "nowhere", - "prayer", - "presence", - "shock", - "snap", - "spider", - "study", - "thunder", - "trail", - "admit", - "agree", - "bag", - "bang", - "bound", - "butterfly", - "cute", - "exactly", - "explode", - "familiar", - "fold", - "further", - "pierce", - "reflect", - "scent", - "selfish", - "sharp", - "sink", - "spring", - "stumble", - "universe", - "weep", - "women", - "wonderful", - "action", - "ancient", - "attempt", - "avoid", - "birthday", - "branch", - "chocolate", - "core", - "depress", - "drunk", - "especially", - "focus", - "fruit", - "honest", - "match", - "palm", - "perfectly", - "pillow", - "pity", - "poison", - "roar", - "shift", - "slightly", - "thump", - "truck", - "tune", - "twenty", - "unable", - "wipe", - "wrote", - "coat", - "constant", - "dinner", - "drove", - "egg", - "eternal", - "flight", - "flood", - "frame", - "freak", - "gasp", - "glad", - "hollow", - "motion", - "peer", - "plastic", - "root", - "screen", - "season", - "sting", - "strike", - "team", - "unlike", - "victim", - "volume", - "warn", - "weird", - "attack", - "await", - "awake", - "built", - "charm", - "crave", - "despair", - "fought", - "grant", - "grief", - "horse", - "limit", - "message", - "ripple", - "sanity", - "scatter", - "serve", - "split", - "string", - "trick", - "annoy", - "blur", - "boat", - "brave", - "clearly", - "cling", - "connect", - "fist", - "forth", - "imagination", - "iron", - "jock", - "judge", - "lesson", - "milk", - "misery", - "nail", - "naked", - "ourselves", - "poet", - "possible", - "princess", - "sail", - "size", - "snake", - "society", - "stroke", - "torture", - "toss", - "trace", - "wise", - "bloom", - "bullet", - "cell", - "check", - "cost", - "darling", - "during", - "footstep", - "fragile", - "hallway", - "hardly", - "horizon", - "invisible", - "journey", - "midnight", - "mud", - "nod", - "pause", - "relax", - "shiver", - "sudden", - "value", - "youth", - "abuse", - "admire", - "blink", - "breast", - "bruise", - "constantly", - "couple", - "creep", - "curve", - "difference", - "dumb", - "emptiness", - "gotta", - "honor", - "plain", - "planet", - "recall", - "rub", - "ship", - "slam", - "soar", - "somebody", - "tightly", - "weather", - "adore", - "approach", - "bond", - "bread", - "burst", - "candle", - "coffee", - "cousin", - "crime", - "desert", - "flutter", - "frozen", - "grand", - "heel", - "hello", - "language", - "level", - "movement", - "pleasure", - "powerful", - "random", - "rhythm", - "settle", - "silly", - "slap", - "sort", - "spoken", - "steel", - "threaten", - "tumble", - "upset", - "aside", - "awkward", - "bee", - "blank", - "board", - "button", - "card", - "carefully", - "complain", - "crap", - "deeply", - "discover", - "drag", - "dread", - "effort", - "entire", - "fairy", - "giant", - "gotten", - "greet", - "illusion", - "jeans", - "leap", - "liquid", - "march", - "mend", - "nervous", - "nine", - "replace", - "rope", - "spine", - "stole", - "terror", - "accident", - "apple", - "balance", - "boom", - "childhood", - "collect", - "demand", - "depression", - "eventually", - "faint", - "glare", - "goal", - "group", - "honey", - "kitchen", - "laid", - "limb", - "machine", - "mere", - "mold", - "murder", - "nerve", - "painful", - "poetry", - "prince", - "rabbit", - "shelter", - "shore", - "shower", - "soothe", - "stair", - "steady", - "sunlight", - "tangle", - "tease", - "treasure", - "uncle", - "begun", - "bliss", - "canvas", - "cheer", - "claw", - "clutch", - "commit", - "crimson", - "crystal", - "delight", - "doll", - "existence", - "express", - "fog", - "football", - "gay", - "goose", - "guard", - "hatred", - "illuminate", - "mass", - "math", - "mourn", - "rich", - "rough", - "skip", - "stir", - "student", - "style", - "support", - "thorn", - "tough", - "yard", - "yearn", - "yesterday", - "advice", - "appreciate", - "autumn", - "bank", - "beam", - "bowl", - "capture", - "carve", - "collapse", - "confusion", - "creation", - "dove", - "feather", - "girlfriend", - "glory", - "government", - "harsh", - "hop", - "inner", - "loser", - "moonlight", - "neighbor", - "neither", - "peach", - "pig", - "praise", - "screw", - "shield", - "shimmer", - "sneak", - "stab", - "subject", - "throughout", - "thrown", - "tower", - "twirl", - "wow", - "army", - "arrive", - "bathroom", - "bump", - "cease", - "cookie", - "couch", - "courage", - "dim", - "guilt", - "howl", - "hum", - "husband", - "insult", - "led", - "lunch", - "mock", - "mostly", - "natural", - "nearly", - "needle", - "nerd", - "peaceful", - "perfection", - "pile", - "price", - "remove", - "roam", - "sanctuary", - "serious", - "shiny", - "shook", - "sob", - "stolen", - "tap", - "vain", - "void", - "warrior", - "wrinkle", - "affection", - "apologize", - "blossom", - "bounce", - "bridge", - "cheap", - "crumble", - "decision", - "descend", - "desperately", - "dig", - "dot", - "flip", - "frighten", - "heartbeat", - "huge", - "lazy", - "lick", - "odd", - "opinion", - "process", - "puzzle", - "quietly", - "retreat", - "score", - "sentence", - "separate", - "situation", - "skill", - "soak", - "square", - "stray", - "taint", - "task", - "tide", - "underneath", - "veil", - "whistle", - "anywhere", - "bedroom", - "bid", - "bloody", - "burden", - "careful", - "compare", - "concern", - "curtain", - "decay", - "defeat", - "describe", - "double", - "dreamer", - "driver", - "dwell", - "evening", - "flare", - "flicker", - "grandma", - "guitar", - "harm", - "horrible", - "hungry", - "indeed", - "lace", - "melody", - "monkey", - "nation", - "object", - "obviously", - "rainbow", - "salt", - "scratch", - "shown", - "shy", - "stage", - "stun", - "third", - "tickle", - "useless", - "weakness", - "worship", - "worthless", - "afternoon", - "beard", - "boyfriend", - "bubble", - "busy", - "certain", - "chin", - "concrete", - "desk", - "diamond", - "doom", - "drawn", - "due", - "felicity", - "freeze", - "frost", - "garden", - "glide", - "harmony", - "hopefully", - "hunt", - "jealous", - "lightning", - "mama", - "mercy", - "peel", - "physical", - "position", - "pulse", - "punch", - "quit", - "rant", - "respond", - "salty", - "sane", - "satisfy", - "savior", - "sheep", - "slept", - "social", - "sport", - "tuck", - "utter", - "valley", - "wolf", - "aim", - "alas", - "alter", - "arrow", - "awaken", - "beaten", - "belief", - "brand", - "ceiling", - "cheese", - "clue", - "confidence", - "connection", - "daily", - "disguise", - "eager", - "erase", - "essence", - "everytime", - "expression", - "fan", - "flag", - "flirt", - "foul", - "fur", - "giggle", - "glorious", - "ignorance", - "law", - "lifeless", - "measure", - "mighty", - "muse", - "north", - "opposite", - "paradise", - "patience", - "patient", - "pencil", - "petal", - "plate", - "ponder", - "possibly", - "practice", - "slice", - "spell", - "stock", - "strife", - "strip", - "suffocate", - "suit", - "tender", - "tool", - "trade", - "velvet", - "verse", - "waist", - "witch", - "aunt", - "bench", - "bold", - "cap", - "certainly", - "click", - "companion", - "creator", - "dart", - "delicate", - "determine", - "dish", - "dragon", - "drama", - "drum", - "dude", - "everybody", - "feast", - "forehead", - "former", - "fright", - "fully", - "gas", - "hook", - "hurl", - "invite", - "juice", - "manage", - "moral", - "possess", - "raw", - "rebel", - "royal", - "scale", - "scary", - "several", - "slight", - "stubborn", - "swell", - "talent", - "tea", - "terrible", - "thread", - "torment", - "trickle", - "usually", - "vast", - "violence", - "weave", - "acid", - "agony", - "ashamed", - "awe", - "belly", - "blend", - "blush", - "character", - "cheat", - "common", - "company", - "coward", - "creak", - "danger", - "deadly", - "defense", - "define", - "depend", - "desperate", - "destination", - "dew", - "duck", - "dusty", - "embarrass", - "engine", - "example", - "explore", - "foe", - "freely", - "frustrate", - "generation", - "glove", - "guilty", - "health", - "hurry", - "idiot", - "impossible", - "inhale", - "jaw", - "kingdom", - "mention", - "mist", - "moan", - "mumble", - "mutter", - "observe", - "ode", - "pathetic", - "pattern", - "pie", - "prefer", - "puff", - "rape", - "rare", - "revenge", - "rude", - "scrape", - "spiral", - "squeeze", - "strain", - "sunset", - "suspend", - "sympathy", - "thigh", - "throne", - "total", - "unseen", - "weapon", - "weary", -} diff --git a/peer.go b/peer.go index 884e296f6..a4da1591b 100644 --- a/peer.go +++ b/peer.go @@ -146,7 +146,7 @@ type Peer struct { } func NewPeer(conn net.Conn, ethereum *Ethereum, inbound bool) *Peer { - pubkey := ethutil.GetKeyRing().Get(0).PublicKey[1:] + pubkey := ethereum.KeyManager().PublicKey()[1:] return &Peer{ outputQueue: make(chan *ethwire.Msg, outputBufferSize), @@ -590,16 +590,12 @@ func (p *Peer) Stop() { } func (p *Peer) pushHandshake() error { - keyRing := ethutil.GetKeyRing().Get(0) - if keyRing != nil { - pubkey := keyRing.PublicKey + pubkey := p.ethereum.KeyManager().PublicKey() + msg := ethwire.NewMessage(ethwire.MsgHandshakeTy, []interface{}{ + uint32(ProtocolVersion), uint32(0), []byte(p.version), byte(p.caps), p.port, pubkey[1:], + }) - msg := ethwire.NewMessage(ethwire.MsgHandshakeTy, []interface{}{ - uint32(ProtocolVersion), uint32(0), []byte(p.version), byte(p.caps), p.port, pubkey[1:], - }) - - p.QueueMessage(msg) - } + p.QueueMessage(msg) return nil } @@ -664,8 +660,8 @@ func (p *Peer) handleHandshake(msg *ethwire.Msg) { p.port = uint16(c.Get(4).Uint()) // Self connect detection - keyPair := ethutil.GetKeyRing().Get(0) - if bytes.Compare(keyPair.PublicKey, p.pubkey) == 0 { + pubkey := p.ethereum.KeyManager().PublicKey() + if bytes.Compare(pubkey, p.pubkey) == 0 { p.Stop() return