forked from cerc-io/plugeth
Merge remote-tracking branch 'origin' into rpcargs
Conflicts: rpc/args.go
This commit is contained in:
commit
6bd1f6cc49
@ -36,9 +36,8 @@ import (
|
|||||||
"bytes"
|
"bytes"
|
||||||
"crypto/ecdsa"
|
"crypto/ecdsa"
|
||||||
crand "crypto/rand"
|
crand "crypto/rand"
|
||||||
"os"
|
|
||||||
|
|
||||||
"errors"
|
"errors"
|
||||||
|
"os"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@ -208,3 +207,37 @@ func zeroKey(k *ecdsa.PrivateKey) {
|
|||||||
b[i] = 0
|
b[i] = 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// USE WITH CAUTION = this will save an unencrypted private key on disk
|
||||||
|
// no cli or js interface
|
||||||
|
func (am *Manager) Export(path string, addr []byte, keyAuth string) error {
|
||||||
|
key, err := am.keyStore.GetKey(addr, keyAuth)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return crypto.SaveECDSA(path, key.PrivateKey)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (am *Manager) Import(path string, keyAuth string) (Account, error) {
|
||||||
|
privateKeyECDSA, err := crypto.LoadECDSA(path)
|
||||||
|
if err != nil {
|
||||||
|
return Account{}, err
|
||||||
|
}
|
||||||
|
key := crypto.NewKeyFromECDSA(privateKeyECDSA)
|
||||||
|
if err = am.keyStore.StoreKey(key, keyAuth); err != nil {
|
||||||
|
return Account{}, err
|
||||||
|
}
|
||||||
|
return Account{Address: key.Address}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (am *Manager) ImportPreSaleKey(keyJSON []byte, password string) (acc Account, err error) {
|
||||||
|
var key *crypto.Key
|
||||||
|
key, err = crypto.ImportPreSaleKey(am.keyStore, keyJSON, password)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err = am.keyStore.StoreKey(key, password); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
return Account{Address: key.Address}, nil
|
||||||
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
package blockpool
|
package blockpool
|
||||||
|
|
||||||
import (
|
import (
|
||||||
// "fmt"
|
"fmt"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@ -45,17 +45,15 @@ func getStatusValues(s *Status) []int {
|
|||||||
func checkStatus(t *testing.T, bp *BlockPool, syncing bool, expected []int) (err error) {
|
func checkStatus(t *testing.T, bp *BlockPool, syncing bool, expected []int) (err error) {
|
||||||
s := bp.Status()
|
s := bp.Status()
|
||||||
if s.Syncing != syncing {
|
if s.Syncing != syncing {
|
||||||
t.Errorf("status for Syncing incorrect. expected %v, got %v", syncing, s.Syncing)
|
err = fmt.Errorf("status for Syncing incorrect. expected %v, got %v", syncing, s.Syncing)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
got := getStatusValues(s)
|
got := getStatusValues(s)
|
||||||
for i, v := range expected {
|
for i, v := range expected {
|
||||||
if i == 0 || i == 7 {
|
|
||||||
continue //hack
|
|
||||||
}
|
|
||||||
err = test.CheckInt(statusFields[i], got[i], v, t)
|
err = test.CheckInt(statusFields[i], got[i], v, t)
|
||||||
// fmt.Printf("%v: %v (%v)\n", statusFields[i], got[i], v)
|
// fmt.Printf("%v: %v (%v)\n", statusFields[i], got[i], v)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
@ -63,6 +61,25 @@ func checkStatus(t *testing.T, bp *BlockPool, syncing bool, expected []int) (err
|
|||||||
|
|
||||||
func TestBlockPoolStatus(t *testing.T) {
|
func TestBlockPoolStatus(t *testing.T) {
|
||||||
test.LogInit()
|
test.LogInit()
|
||||||
|
var err error
|
||||||
|
n := 3
|
||||||
|
for n > 0 {
|
||||||
|
n--
|
||||||
|
err = testBlockPoolStatus(t)
|
||||||
|
if err != nil {
|
||||||
|
t.Log(err)
|
||||||
|
continue
|
||||||
|
} else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("no pass out of 3: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func testBlockPoolStatus(t *testing.T) (err error) {
|
||||||
|
|
||||||
_, blockPool, blockPoolTester := newTestBlockPool(t)
|
_, blockPool, blockPoolTester := newTestBlockPool(t)
|
||||||
blockPoolTester.blockChain[0] = nil
|
blockPoolTester.blockChain[0] = nil
|
||||||
blockPoolTester.initRefBlockChain(12)
|
blockPoolTester.initRefBlockChain(12)
|
||||||
@ -70,6 +87,7 @@ func TestBlockPoolStatus(t *testing.T) {
|
|||||||
delete(blockPoolTester.refBlockChain, 6)
|
delete(blockPoolTester.refBlockChain, 6)
|
||||||
|
|
||||||
blockPool.Start()
|
blockPool.Start()
|
||||||
|
defer blockPool.Stop()
|
||||||
blockPoolTester.tds = make(map[int]int)
|
blockPoolTester.tds = make(map[int]int)
|
||||||
blockPoolTester.tds[9] = 1
|
blockPoolTester.tds[9] = 1
|
||||||
blockPoolTester.tds[11] = 3
|
blockPoolTester.tds[11] = 3
|
||||||
@ -79,73 +97,67 @@ func TestBlockPoolStatus(t *testing.T) {
|
|||||||
peer2 := blockPoolTester.newPeer("peer2", 2, 6)
|
peer2 := blockPoolTester.newPeer("peer2", 2, 6)
|
||||||
peer3 := blockPoolTester.newPeer("peer3", 3, 11)
|
peer3 := blockPoolTester.newPeer("peer3", 3, 11)
|
||||||
peer4 := blockPoolTester.newPeer("peer4", 1, 9)
|
peer4 := blockPoolTester.newPeer("peer4", 1, 9)
|
||||||
// peer1 := blockPoolTester.newPeer("peer1", 1, 9)
|
|
||||||
// peer2 := blockPoolTester.newPeer("peer2", 2, 6)
|
|
||||||
// peer3 := blockPoolTester.newPeer("peer3", 3, 11)
|
|
||||||
// peer4 := blockPoolTester.newPeer("peer4", 1, 9)
|
|
||||||
peer2.blocksRequestsMap = peer1.blocksRequestsMap
|
peer2.blocksRequestsMap = peer1.blocksRequestsMap
|
||||||
|
|
||||||
var expected []int
|
var expected []int
|
||||||
var err error
|
|
||||||
expected = []int{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
|
expected = []int{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
|
||||||
err = checkStatus(t, blockPool, false, expected)
|
err = checkStatus(nil, blockPool, false, expected)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
peer1.AddPeer()
|
peer1.AddPeer()
|
||||||
expected = []int{0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 1, 0}
|
expected = []int{0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 1, 0}
|
||||||
err = checkStatus(t, blockPool, true, expected)
|
err = checkStatus(nil, blockPool, true, expected)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
peer1.serveBlocks(8, 9)
|
peer1.serveBlocks(8, 9)
|
||||||
expected = []int{0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 1, 1, 0}
|
expected = []int{1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 1, 1, 0}
|
||||||
// err = checkStatus(t, blockPool, true, expected)
|
err = checkStatus(nil, blockPool, true, expected)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
peer1.serveBlockHashes(9, 8, 7, 3, 2)
|
peer1.serveBlockHashes(9, 8, 7, 3, 2)
|
||||||
expected = []int{6, 5, 1, 1, 0, 1, 0, 0, 1, 1, 1, 1, 0}
|
expected = []int{6, 5, 1, 1, 0, 1, 0, 0, 1, 1, 1, 1, 0}
|
||||||
// expected = []int{5, 5, 1, 1, 0, 1, 0, 0, 1, 1, 1, 1, 0}
|
err = checkStatus(nil, blockPool, true, expected)
|
||||||
err = checkStatus(t, blockPool, true, expected)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
peer1.serveBlocks(3, 7, 8)
|
peer1.serveBlocks(3, 7, 8)
|
||||||
expected = []int{6, 5, 3, 3, 0, 1, 0, 0, 1, 1, 1, 1, 0}
|
expected = []int{6, 5, 3, 3, 0, 1, 0, 0, 1, 1, 1, 1, 0}
|
||||||
err = checkStatus(t, blockPool, true, expected)
|
err = checkStatus(nil, blockPool, true, expected)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
peer1.serveBlocks(2, 3)
|
peer1.serveBlocks(2, 3)
|
||||||
expected = []int{6, 5, 4, 4, 0, 1, 0, 0, 1, 1, 1, 1, 0}
|
expected = []int{6, 5, 4, 4, 0, 1, 0, 0, 1, 1, 1, 1, 0}
|
||||||
err = checkStatus(t, blockPool, true, expected)
|
err = checkStatus(nil, blockPool, true, expected)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
peer4.AddPeer()
|
peer4.AddPeer()
|
||||||
expected = []int{6, 5, 4, 4, 0, 2, 0, 0, 2, 2, 1, 1, 0}
|
expected = []int{6, 5, 4, 4, 0, 2, 0, 0, 2, 2, 1, 1, 0}
|
||||||
err = checkStatus(t, blockPool, true, expected)
|
err = checkStatus(nil, blockPool, true, expected)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
peer4.sendBlockHashes(12, 11)
|
peer4.sendBlockHashes(12, 11)
|
||||||
expected = []int{6, 5, 4, 4, 0, 2, 0, 0, 2, 2, 1, 1, 0}
|
expected = []int{6, 5, 4, 4, 0, 2, 0, 0, 2, 2, 1, 1, 0}
|
||||||
err = checkStatus(t, blockPool, true, expected)
|
err = checkStatus(nil, blockPool, true, expected)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
peer2.AddPeer()
|
peer2.AddPeer()
|
||||||
expected = []int{6, 5, 4, 4, 0, 3, 0, 0, 3, 3, 1, 2, 0}
|
expected = []int{6, 5, 4, 4, 0, 3, 0, 0, 3, 3, 1, 2, 0}
|
||||||
err = checkStatus(t, blockPool, true, expected)
|
err = checkStatus(nil, blockPool, true, expected)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -153,76 +165,76 @@ func TestBlockPoolStatus(t *testing.T) {
|
|||||||
peer2.serveBlocks(5, 6)
|
peer2.serveBlocks(5, 6)
|
||||||
peer2.serveBlockHashes(6, 5, 4, 3, 2)
|
peer2.serveBlockHashes(6, 5, 4, 3, 2)
|
||||||
expected = []int{10, 8, 5, 5, 0, 3, 1, 0, 3, 3, 2, 2, 0}
|
expected = []int{10, 8, 5, 5, 0, 3, 1, 0, 3, 3, 2, 2, 0}
|
||||||
err = checkStatus(t, blockPool, true, expected)
|
err = checkStatus(nil, blockPool, true, expected)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
peer2.serveBlocks(2, 3, 4)
|
peer2.serveBlocks(2, 3, 4)
|
||||||
expected = []int{10, 8, 6, 6, 0, 3, 1, 0, 3, 3, 2, 2, 0}
|
expected = []int{10, 8, 6, 6, 0, 3, 1, 0, 3, 3, 2, 2, 0}
|
||||||
err = checkStatus(t, blockPool, true, expected)
|
err = checkStatus(nil, blockPool, true, expected)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
blockPool.RemovePeer("peer2")
|
blockPool.RemovePeer("peer2")
|
||||||
expected = []int{10, 8, 6, 6, 0, 3, 1, 0, 3, 2, 2, 2, 0}
|
expected = []int{10, 8, 6, 6, 0, 3, 1, 0, 3, 2, 2, 2, 0}
|
||||||
err = checkStatus(t, blockPool, true, expected)
|
err = checkStatus(nil, blockPool, true, expected)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
peer1.serveBlockHashes(2, 1, 0)
|
peer1.serveBlockHashes(2, 1, 0)
|
||||||
expected = []int{11, 9, 6, 6, 0, 3, 1, 0, 3, 2, 2, 2, 0}
|
expected = []int{11, 9, 6, 6, 0, 3, 1, 0, 3, 2, 2, 2, 0}
|
||||||
err = checkStatus(t, blockPool, true, expected)
|
err = checkStatus(nil, blockPool, true, expected)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
peer1.serveBlocks(1, 2)
|
peer1.serveBlocks(1, 2)
|
||||||
expected = []int{11, 9, 7, 7, 0, 3, 1, 0, 3, 2, 2, 2, 0}
|
expected = []int{11, 9, 7, 7, 0, 3, 1, 0, 3, 2, 2, 2, 0}
|
||||||
err = checkStatus(t, blockPool, true, expected)
|
err = checkStatus(nil, blockPool, true, expected)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
peer1.serveBlocks(4, 5)
|
peer1.serveBlocks(4, 5)
|
||||||
expected = []int{11, 9, 8, 8, 0, 3, 1, 0, 3, 2, 2, 2, 0}
|
expected = []int{11, 9, 8, 8, 0, 3, 1, 0, 3, 2, 2, 2, 0}
|
||||||
err = checkStatus(t, blockPool, true, expected)
|
err = checkStatus(nil, blockPool, true, expected)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
peer3.AddPeer()
|
peer3.AddPeer()
|
||||||
expected = []int{11, 9, 8, 8, 0, 4, 1, 0, 4, 3, 2, 3, 0}
|
expected = []int{11, 9, 8, 8, 0, 4, 1, 0, 4, 3, 2, 3, 0}
|
||||||
err = checkStatus(t, blockPool, true, expected)
|
err = checkStatus(nil, blockPool, true, expected)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
peer3.serveBlocks(10, 11)
|
peer3.serveBlocks(10, 11)
|
||||||
expected = []int{12, 9, 9, 9, 0, 4, 1, 0, 4, 3, 3, 3, 0}
|
expected = []int{12, 9, 9, 9, 0, 4, 1, 0, 4, 3, 3, 3, 0}
|
||||||
err = checkStatus(t, blockPool, true, expected)
|
err = checkStatus(nil, blockPool, true, expected)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
peer3.serveBlockHashes(11, 10, 9)
|
peer3.serveBlockHashes(11, 10, 9)
|
||||||
expected = []int{14, 11, 9, 9, 0, 4, 1, 0, 4, 3, 3, 3, 0}
|
expected = []int{14, 11, 9, 9, 0, 4, 1, 0, 4, 3, 3, 3, 0}
|
||||||
err = checkStatus(t, blockPool, true, expected)
|
err = checkStatus(nil, blockPool, true, expected)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
peer4.sendBlocks(11, 12)
|
peer4.sendBlocks(11, 12)
|
||||||
expected = []int{14, 11, 9, 9, 0, 4, 1, 0, 4, 3, 4, 3, 1}
|
expected = []int{14, 11, 9, 9, 0, 4, 1, 0, 4, 3, 4, 3, 1}
|
||||||
err = checkStatus(t, blockPool, true, expected)
|
err = checkStatus(nil, blockPool, true, expected)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
peer3.serveBlocks(9, 10)
|
peer3.serveBlocks(9, 10)
|
||||||
expected = []int{14, 11, 10, 10, 0, 4, 1, 0, 4, 3, 4, 3, 1}
|
expected = []int{14, 11, 10, 10, 0, 4, 1, 0, 4, 3, 4, 3, 1}
|
||||||
err = checkStatus(t, blockPool, true, expected)
|
err = checkStatus(nil, blockPool, true, expected)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -231,10 +243,9 @@ func TestBlockPoolStatus(t *testing.T) {
|
|||||||
blockPool.Wait(waitTimeout)
|
blockPool.Wait(waitTimeout)
|
||||||
time.Sleep(200 * time.Millisecond)
|
time.Sleep(200 * time.Millisecond)
|
||||||
expected = []int{14, 3, 11, 3, 8, 4, 1, 8, 4, 3, 4, 3, 1}
|
expected = []int{14, 3, 11, 3, 8, 4, 1, 8, 4, 3, 4, 3, 1}
|
||||||
err = checkStatus(t, blockPool, false, expected)
|
err = checkStatus(nil, blockPool, false, expected)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
return nil
|
||||||
blockPool.Stop()
|
|
||||||
}
|
}
|
||||||
|
@ -10,16 +10,20 @@ import (
|
|||||||
|
|
||||||
func CheckInt(name string, got int, expected int, t *testing.T) (err error) {
|
func CheckInt(name string, got int, expected int, t *testing.T) (err error) {
|
||||||
if got != expected {
|
if got != expected {
|
||||||
t.Errorf("status for %v incorrect. expected %v, got %v", name, expected, got)
|
err = fmt.Errorf("status for %v incorrect. expected %v, got %v", name, expected, got)
|
||||||
err = fmt.Errorf("")
|
if t != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func CheckDuration(name string, got time.Duration, expected time.Duration, t *testing.T) (err error) {
|
func CheckDuration(name string, got time.Duration, expected time.Duration, t *testing.T) (err error) {
|
||||||
if got != expected {
|
if got != expected {
|
||||||
t.Errorf("status for %v incorrect. expected %v, got %v", name, expected, got)
|
err = fmt.Errorf("status for %v incorrect. expected %v, got %v", name, expected, got)
|
||||||
err = fmt.Errorf("")
|
if t != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -67,14 +67,14 @@ type jsre struct {
|
|||||||
prompter
|
prompter
|
||||||
}
|
}
|
||||||
|
|
||||||
func newJSRE(ethereum *eth.Ethereum, libPath string) *jsre {
|
func newJSRE(ethereum *eth.Ethereum, libPath string, interactive bool) *jsre {
|
||||||
js := &jsre{ethereum: ethereum, ps1: "> "}
|
js := &jsre{ethereum: ethereum, ps1: "> "}
|
||||||
js.xeth = xeth.New(ethereum, js)
|
js.xeth = xeth.New(ethereum, js)
|
||||||
js.re = re.New(libPath)
|
js.re = re.New(libPath)
|
||||||
js.apiBindings()
|
js.apiBindings()
|
||||||
js.adminBindings()
|
js.adminBindings()
|
||||||
|
|
||||||
if !liner.TerminalSupported() {
|
if !liner.TerminalSupported() || !interactive {
|
||||||
js.prompter = dumbterm{bufio.NewReader(os.Stdin)}
|
js.prompter = dumbterm{bufio.NewReader(os.Stdin)}
|
||||||
} else {
|
} else {
|
||||||
lr := liner.NewLiner()
|
lr := liner.NewLiner()
|
||||||
@ -102,7 +102,7 @@ func (js *jsre) apiBindings() {
|
|||||||
jethObj := t.Object()
|
jethObj := t.Object()
|
||||||
jethObj.Set("send", jeth.Send)
|
jethObj.Set("send", jeth.Send)
|
||||||
|
|
||||||
err := js.re.Compile("bignum.js", re.BigNumber_JS)
|
err := js.re.Compile("bignumber.js", re.BigNumber_JS)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
utils.Fatalf("Error loading bignumber.js: %v", err)
|
utils.Fatalf("Error loading bignumber.js: %v", err)
|
||||||
}
|
}
|
@ -2,6 +2,7 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
"path"
|
"path"
|
||||||
"testing"
|
"testing"
|
||||||
@ -9,7 +10,6 @@ import (
|
|||||||
"github.com/robertkrimen/otto"
|
"github.com/robertkrimen/otto"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/accounts"
|
"github.com/ethereum/go-ethereum/accounts"
|
||||||
"github.com/ethereum/go-ethereum/common"
|
|
||||||
"github.com/ethereum/go-ethereum/crypto"
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
"github.com/ethereum/go-ethereum/eth"
|
"github.com/ethereum/go-ethereum/eth"
|
||||||
)
|
)
|
||||||
@ -30,8 +30,8 @@ func testJEthRE(t *testing.T) (repl *jsre, ethereum *eth.Ethereum, err error) {
|
|||||||
}
|
}
|
||||||
// FIXME: this does not work ATM
|
// FIXME: this does not work ATM
|
||||||
ks := crypto.NewKeyStorePlain("/tmp/eth/keys")
|
ks := crypto.NewKeyStorePlain("/tmp/eth/keys")
|
||||||
common.WriteFile("/tmp/eth/keys/e273f01c99144c438695e10f24926dc1f9fbf62d/e273f01c99144c438695e10f24926dc1f9fbf62d",
|
ioutil.WriteFile("/tmp/eth/keys/e273f01c99144c438695e10f24926dc1f9fbf62d/e273f01c99144c438695e10f24926dc1f9fbf62d",
|
||||||
[]byte(`{"Id":"RhRXD+fNRKS4jx+7ZfEsNA==","Address":"4nPwHJkUTEOGleEPJJJtwfn79i0=","PrivateKey":"h4ACVpe74uIvi5Cg/2tX/Yrm2xdr3J7QoMbMtNX2CNc="}`))
|
[]byte(`{"Id":"RhRXD+fNRKS4jx+7ZfEsNA==","Address":"4nPwHJkUTEOGleEPJJJtwfn79i0=","PrivateKey":"h4ACVpe74uIvi5Cg/2tX/Yrm2xdr3J7QoMbMtNX2CNc="}`), os.ModePerm)
|
||||||
|
|
||||||
port++
|
port++
|
||||||
ethereum, err = eth.New(ð.Config{
|
ethereum, err = eth.New(ð.Config{
|
||||||
@ -47,7 +47,7 @@ func testJEthRE(t *testing.T) (repl *jsre, ethereum *eth.Ethereum, err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
assetPath := path.Join(os.Getenv("GOPATH"), "src", "github.com", "ethereum", "go-ethereum", "cmd", "mist", "assets", "ext")
|
assetPath := path.Join(os.Getenv("GOPATH"), "src", "github.com", "ethereum", "go-ethereum", "cmd", "mist", "assets", "ext")
|
||||||
repl = newJSRE(ethereum, assetPath)
|
repl = newJSRE(ethereum, assetPath, false)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
@ -23,14 +23,15 @@ package main
|
|||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
"runtime"
|
"runtime"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/codegangsta/cli"
|
"github.com/codegangsta/cli"
|
||||||
"github.com/ethereum/ethash"
|
"github.com/ethereum/ethash"
|
||||||
|
"github.com/ethereum/go-ethereum/accounts"
|
||||||
"github.com/ethereum/go-ethereum/cmd/utils"
|
"github.com/ethereum/go-ethereum/cmd/utils"
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/core/state"
|
"github.com/ethereum/go-ethereum/core/state"
|
||||||
@ -41,8 +42,8 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
ClientIdentifier = "Ethereum(G)"
|
ClientIdentifier = "Geth"
|
||||||
Version = "0.9.3"
|
Version = "0.9.4"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@ -74,10 +75,44 @@ Regular users do not need to execute it.
|
|||||||
The output of this command is supposed to be machine-readable.
|
The output of this command is supposed to be machine-readable.
|
||||||
`,
|
`,
|
||||||
},
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
Name: "wallet",
|
||||||
|
Usage: "ethereum presale wallet",
|
||||||
|
Subcommands: []cli.Command{
|
||||||
|
{
|
||||||
|
Action: importWallet,
|
||||||
|
Name: "import",
|
||||||
|
Usage: "import ethereum presale wallet",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
Action: accountList,
|
Action: accountList,
|
||||||
Name: "account",
|
Name: "account",
|
||||||
Usage: "manage accounts",
|
Usage: "manage accounts",
|
||||||
|
Description: `
|
||||||
|
|
||||||
|
Manage accounts lets you create new accounts, list all existing accounts,
|
||||||
|
import a private key into a new account.
|
||||||
|
|
||||||
|
It supports interactive mode, when you are prompted for password as well as
|
||||||
|
non-interactive mode where passwords are supplied via a given password file.
|
||||||
|
Non-interactive mode is only meant for scripted use on test networks or known
|
||||||
|
safe environments.
|
||||||
|
|
||||||
|
Make sure you remember the password you gave when creating a new account (with
|
||||||
|
either new or import). Without it you are not able to unlock your account.
|
||||||
|
|
||||||
|
Note that exporting your key in unencrypted format is NOT supported.
|
||||||
|
|
||||||
|
Keys are stored under <DATADIR>/keys.
|
||||||
|
It is safe to transfer the entire directory or the individual keys therein
|
||||||
|
between ethereum nodes.
|
||||||
|
Make sure you backup your keys regularly.
|
||||||
|
|
||||||
|
And finally. DO NOT FORGET YOUR PASSWORD.
|
||||||
|
`,
|
||||||
Subcommands: []cli.Command{
|
Subcommands: []cli.Command{
|
||||||
{
|
{
|
||||||
Action: accountList,
|
Action: accountList,
|
||||||
@ -88,6 +123,51 @@ The output of this command is supposed to be machine-readable.
|
|||||||
Action: accountCreate,
|
Action: accountCreate,
|
||||||
Name: "new",
|
Name: "new",
|
||||||
Usage: "create a new account",
|
Usage: "create a new account",
|
||||||
|
Description: `
|
||||||
|
|
||||||
|
ethereum account new
|
||||||
|
|
||||||
|
Creates a new account. Prints the address.
|
||||||
|
|
||||||
|
The account is saved in encrypted format, you are prompted for a passphrase.
|
||||||
|
|
||||||
|
You must remember this passphrase to unlock your account in the future.
|
||||||
|
|
||||||
|
For non-interactive use the passphrase can be specified with the --password flag:
|
||||||
|
|
||||||
|
ethereum --password <passwordfile> account new
|
||||||
|
|
||||||
|
Note, this is meant to be used for testing only, it is a bad idea to save your
|
||||||
|
password to file or expose in any other way.
|
||||||
|
`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Action: accountImport,
|
||||||
|
Name: "import",
|
||||||
|
Usage: "import a private key into a new account",
|
||||||
|
Description: `
|
||||||
|
|
||||||
|
ethereum account import <keyfile>
|
||||||
|
|
||||||
|
Imports an unencrypted private key from <keyfile> and creates a new account.
|
||||||
|
Prints the address.
|
||||||
|
|
||||||
|
The keyfile is assumed to contain an unencrypted private key in canonical EC
|
||||||
|
raw bytes format.
|
||||||
|
|
||||||
|
The account is saved in encrypted format, you are prompted for a passphrase.
|
||||||
|
|
||||||
|
You must remember this passphrase to unlock your account in the future.
|
||||||
|
|
||||||
|
For non-interactive use the passphrase can be specified with the -password flag:
|
||||||
|
|
||||||
|
ethereum --password <passwordfile> account import <keyfile>
|
||||||
|
|
||||||
|
Note:
|
||||||
|
As you can directly copy your encrypted accounts to another ethereum instance,
|
||||||
|
this import mechanism is not needed when you transfer an account between
|
||||||
|
nodes.
|
||||||
|
`,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -103,18 +183,20 @@ Use "ethereum dump 0" to dump the genesis block.
|
|||||||
{
|
{
|
||||||
Action: console,
|
Action: console,
|
||||||
Name: "console",
|
Name: "console",
|
||||||
Usage: `Ethereum Console: interactive JavaScript environment`,
|
Usage: `Geth Console: interactive JavaScript environment`,
|
||||||
Description: `
|
Description: `
|
||||||
Console is an interactive shell for the Ethereum JavaScript runtime environment which exposes a node admin interface as well as the DAPP JavaScript API.
|
The Geth console is an interactive shell for the JavaScript runtime environment
|
||||||
|
which exposes a node admin interface as well as the DAPP JavaScript API.
|
||||||
See https://github.com/ethereum/go-ethereum/wiki/Frontier-Console
|
See https://github.com/ethereum/go-ethereum/wiki/Frontier-Console
|
||||||
`,
|
`,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Action: execJSFiles,
|
Action: execJSFiles,
|
||||||
Name: "js",
|
Name: "js",
|
||||||
Usage: `executes the given JavaScript files in the Ethereum Frontier JavaScript VM`,
|
Usage: `executes the given JavaScript files in the Geth JavaScript VM`,
|
||||||
Description: `
|
Description: `
|
||||||
The Ethereum JavaScript VM exposes a node admin interface as well as the DAPP JavaScript API. See https://github.com/ethereum/go-ethereum/wiki/Frontier-Console
|
The JavaScript VM exposes a node admin interface as well as the DAPP
|
||||||
|
JavaScript API. See https://github.com/ethereum/go-ethereum/wiki/Javascipt-Console
|
||||||
`,
|
`,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -130,6 +212,7 @@ The Ethereum JavaScript VM exposes a node admin interface as well as the DAPP Ja
|
|||||||
}
|
}
|
||||||
app.Flags = []cli.Flag{
|
app.Flags = []cli.Flag{
|
||||||
utils.UnlockedAccountFlag,
|
utils.UnlockedAccountFlag,
|
||||||
|
utils.PasswordFileFlag,
|
||||||
utils.BootnodesFlag,
|
utils.BootnodesFlag,
|
||||||
utils.DataDirFlag,
|
utils.DataDirFlag,
|
||||||
utils.JSpathFlag,
|
utils.JSpathFlag,
|
||||||
@ -146,7 +229,6 @@ The Ethereum JavaScript VM exposes a node admin interface as well as the DAPP Ja
|
|||||||
utils.RPCEnabledFlag,
|
utils.RPCEnabledFlag,
|
||||||
utils.RPCListenAddrFlag,
|
utils.RPCListenAddrFlag,
|
||||||
utils.RPCPortFlag,
|
utils.RPCPortFlag,
|
||||||
utils.UnencryptedKeysFlag,
|
|
||||||
utils.VMDebugFlag,
|
utils.VMDebugFlag,
|
||||||
utils.ProtocolVersionFlag,
|
utils.ProtocolVersionFlag,
|
||||||
utils.NetworkIdFlag,
|
utils.NetworkIdFlag,
|
||||||
@ -194,7 +276,7 @@ func console(ctx *cli.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
startEth(ctx, ethereum)
|
startEth(ctx, ethereum)
|
||||||
repl := newJSRE(ethereum, ctx.String(utils.JSpathFlag.Name))
|
repl := newJSRE(ethereum, ctx.String(utils.JSpathFlag.Name), true)
|
||||||
repl.interactive()
|
repl.interactive()
|
||||||
|
|
||||||
ethereum.Stop()
|
ethereum.Stop()
|
||||||
@ -209,7 +291,7 @@ func execJSFiles(ctx *cli.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
startEth(ctx, ethereum)
|
startEth(ctx, ethereum)
|
||||||
repl := newJSRE(ethereum, ctx.String(utils.JSpathFlag.Name))
|
repl := newJSRE(ethereum, ctx.String(utils.JSpathFlag.Name), false)
|
||||||
for _, file := range ctx.Args() {
|
for _, file := range ctx.Args() {
|
||||||
repl.exec(file)
|
repl.exec(file)
|
||||||
}
|
}
|
||||||
@ -218,22 +300,36 @@ func execJSFiles(ctx *cli.Context) {
|
|||||||
ethereum.WaitForShutdown()
|
ethereum.WaitForShutdown()
|
||||||
}
|
}
|
||||||
|
|
||||||
func startEth(ctx *cli.Context, eth *eth.Ethereum) {
|
func unlockAccount(ctx *cli.Context, am *accounts.Manager, account string) (passphrase string) {
|
||||||
utils.StartEthereum(eth)
|
var err error
|
||||||
|
|
||||||
// Load startup keys. XXX we are going to need a different format
|
// Load startup keys. XXX we are going to need a different format
|
||||||
account := ctx.GlobalString(utils.UnlockedAccountFlag.Name)
|
|
||||||
if len(account) > 0 {
|
|
||||||
split := strings.Split(account, ":")
|
|
||||||
if len(split) != 2 {
|
|
||||||
utils.Fatalf("Illegal 'unlock' format (address:password)")
|
|
||||||
}
|
|
||||||
am := eth.AccountManager()
|
|
||||||
// Attempt to unlock the account
|
// Attempt to unlock the account
|
||||||
err := am.Unlock(common.FromHex(split[0]), split[1])
|
passphrase = getPassPhrase(ctx, "", false)
|
||||||
|
accbytes := common.FromHex(account)
|
||||||
|
if len(accbytes) == 0 {
|
||||||
|
utils.Fatalf("Invalid account address '%s'", account)
|
||||||
|
}
|
||||||
|
err = am.Unlock(accbytes, passphrase)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
utils.Fatalf("Unlock account failed '%v'", err)
|
utils.Fatalf("Unlock account failed '%v'", err)
|
||||||
}
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func startEth(ctx *cli.Context, eth *eth.Ethereum) {
|
||||||
|
utils.StartEthereum(eth)
|
||||||
|
am := eth.AccountManager()
|
||||||
|
|
||||||
|
account := ctx.GlobalString(utils.UnlockedAccountFlag.Name)
|
||||||
|
if len(account) > 0 {
|
||||||
|
if account == "coinbase" {
|
||||||
|
accbytes, err := am.Coinbase()
|
||||||
|
if err != nil {
|
||||||
|
utils.Fatalf("no coinbase account: %v", err)
|
||||||
|
}
|
||||||
|
account = common.ToHex(accbytes)
|
||||||
|
}
|
||||||
|
unlockAccount(ctx, am, account)
|
||||||
}
|
}
|
||||||
// Start auxiliary services if enabled.
|
// Start auxiliary services if enabled.
|
||||||
if ctx.GlobalBool(utils.RPCEnabledFlag.Name) {
|
if ctx.GlobalBool(utils.RPCEnabledFlag.Name) {
|
||||||
@ -255,16 +351,15 @@ func accountList(ctx *cli.Context) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func accountCreate(ctx *cli.Context) {
|
func getPassPhrase(ctx *cli.Context, desc string, confirmation bool) (passphrase string) {
|
||||||
am := utils.GetAccountManager(ctx)
|
passfile := ctx.GlobalString(utils.PasswordFileFlag.Name)
|
||||||
passphrase := ""
|
if len(passfile) == 0 {
|
||||||
if !ctx.GlobalBool(utils.UnencryptedKeysFlag.Name) {
|
fmt.Println(desc)
|
||||||
fmt.Println("The new account will be encrypted with a passphrase.")
|
|
||||||
fmt.Println("Please enter a passphrase now.")
|
|
||||||
auth, err := readPassword("Passphrase: ", true)
|
auth, err := readPassword("Passphrase: ", true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
utils.Fatalf("%v", err)
|
utils.Fatalf("%v", err)
|
||||||
}
|
}
|
||||||
|
if confirmation {
|
||||||
confirm, err := readPassword("Repeat Passphrase: ", false)
|
confirm, err := readPassword("Repeat Passphrase: ", false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
utils.Fatalf("%v", err)
|
utils.Fatalf("%v", err)
|
||||||
@ -272,13 +367,61 @@ func accountCreate(ctx *cli.Context) {
|
|||||||
if auth != confirm {
|
if auth != confirm {
|
||||||
utils.Fatalf("Passphrases did not match.")
|
utils.Fatalf("Passphrases did not match.")
|
||||||
}
|
}
|
||||||
passphrase = auth
|
|
||||||
}
|
}
|
||||||
|
passphrase = auth
|
||||||
|
|
||||||
|
} else {
|
||||||
|
passbytes, err := ioutil.ReadFile(passfile)
|
||||||
|
if err != nil {
|
||||||
|
utils.Fatalf("Unable to read password file '%s': %v", passfile, err)
|
||||||
|
}
|
||||||
|
passphrase = string(passbytes)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func accountCreate(ctx *cli.Context) {
|
||||||
|
am := utils.GetAccountManager(ctx)
|
||||||
|
passphrase := getPassPhrase(ctx, "Your new account is locked with a password. Please give a password. Do not forget this password.", true)
|
||||||
acct, err := am.NewAccount(passphrase)
|
acct, err := am.NewAccount(passphrase)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
utils.Fatalf("Could not create the account: %v", err)
|
utils.Fatalf("Could not create the account: %v", err)
|
||||||
}
|
}
|
||||||
fmt.Printf("Address: %x\n", acct.Address)
|
fmt.Printf("Address: %x\n", acct)
|
||||||
|
}
|
||||||
|
|
||||||
|
func importWallet(ctx *cli.Context) {
|
||||||
|
keyfile := ctx.Args().First()
|
||||||
|
if len(keyfile) == 0 {
|
||||||
|
utils.Fatalf("keyfile must be given as argument")
|
||||||
|
}
|
||||||
|
keyJson, err := ioutil.ReadFile(keyfile)
|
||||||
|
if err != nil {
|
||||||
|
utils.Fatalf("Could not read wallet file: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
am := utils.GetAccountManager(ctx)
|
||||||
|
passphrase := getPassPhrase(ctx, "", false)
|
||||||
|
|
||||||
|
acct, err := am.ImportPreSaleKey(keyJson, passphrase)
|
||||||
|
if err != nil {
|
||||||
|
utils.Fatalf("Could not create the account: %v", err)
|
||||||
|
}
|
||||||
|
fmt.Printf("Address: %x\n", acct)
|
||||||
|
}
|
||||||
|
|
||||||
|
func accountImport(ctx *cli.Context) {
|
||||||
|
keyfile := ctx.Args().First()
|
||||||
|
if len(keyfile) == 0 {
|
||||||
|
utils.Fatalf("keyfile must be given as argument")
|
||||||
|
}
|
||||||
|
am := utils.GetAccountManager(ctx)
|
||||||
|
passphrase := getPassPhrase(ctx, "Your new account is locked with a password. Please give a password. Do not forget this password.", true)
|
||||||
|
acct, err := am.Import(keyfile, passphrase)
|
||||||
|
if err != nil {
|
||||||
|
utils.Fatalf("Could not create the account: %v", err)
|
||||||
|
}
|
||||||
|
fmt.Printf("Address: %x\n", acct)
|
||||||
}
|
}
|
||||||
|
|
||||||
func importchain(ctx *cli.Context) {
|
func importchain(ctx *cli.Context) {
|
@ -1 +1 @@
|
|||||||
Subproject commit 9f073d9091cd2d2b46dd46afea9dcf5d825ecd7c
|
Subproject commit 17164bea8b330d6a118b40d6fbe222ffb12a0e9f
|
@ -22,13 +22,14 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/cmd/utils"
|
"github.com/ethereum/go-ethereum/cmd/utils"
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
|
||||||
"github.com/ethereum/go-ethereum/core/state"
|
"github.com/ethereum/go-ethereum/core/state"
|
||||||
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
type plugin struct {
|
type plugin struct {
|
||||||
@ -46,14 +47,14 @@ func (self *Gui) AddPlugin(pluginPath string) {
|
|||||||
self.plugins[pluginPath] = plugin{Name: pluginPath, Path: pluginPath}
|
self.plugins[pluginPath] = plugin{Name: pluginPath, Path: pluginPath}
|
||||||
|
|
||||||
json, _ := json.MarshalIndent(self.plugins, "", " ")
|
json, _ := json.MarshalIndent(self.plugins, "", " ")
|
||||||
common.WriteFile(self.eth.DataDir+"/plugins.json", json)
|
ioutil.WriteFile(self.eth.DataDir+"/plugins.json", json, os.ModePerm)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *Gui) RemovePlugin(pluginPath string) {
|
func (self *Gui) RemovePlugin(pluginPath string) {
|
||||||
delete(self.plugins, pluginPath)
|
delete(self.plugins, pluginPath)
|
||||||
|
|
||||||
json, _ := json.MarshalIndent(self.plugins, "", " ")
|
json, _ := json.MarshalIndent(self.plugins, "", " ")
|
||||||
common.WriteFile(self.eth.DataDir+"/plugins.json", json)
|
ioutil.WriteFile(self.eth.DataDir+"/plugins.json", json, os.ModePerm)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *Gui) DumpState(hash, path string) {
|
func (self *Gui) DumpState(hash, path string) {
|
||||||
|
@ -25,6 +25,7 @@ import "C"
|
|||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
"math/big"
|
"math/big"
|
||||||
"path"
|
"path"
|
||||||
"runtime"
|
"runtime"
|
||||||
@ -91,8 +92,8 @@ func NewWindow(ethereum *eth.Ethereum) *Gui {
|
|||||||
plugins: make(map[string]plugin),
|
plugins: make(map[string]plugin),
|
||||||
serviceEvents: make(chan ServEv, 1),
|
serviceEvents: make(chan ServEv, 1),
|
||||||
}
|
}
|
||||||
data, _ := common.ReadAllFile(path.Join(ethereum.DataDir, "plugins.json"))
|
data, _ := ioutil.ReadFile(path.Join(ethereum.DataDir, "plugins.json"))
|
||||||
json.Unmarshal([]byte(data), &gui.plugins)
|
json.Unmarshal(data, &gui.plugins)
|
||||||
|
|
||||||
return gui
|
return gui
|
||||||
}
|
}
|
||||||
|
@ -97,14 +97,15 @@ var (
|
|||||||
Usage: "Enable mining",
|
Usage: "Enable mining",
|
||||||
}
|
}
|
||||||
|
|
||||||
// key settings
|
|
||||||
UnencryptedKeysFlag = cli.BoolFlag{
|
|
||||||
Name: "unencrypted-keys",
|
|
||||||
Usage: "disable private key disk encryption (for testing)",
|
|
||||||
}
|
|
||||||
UnlockedAccountFlag = cli.StringFlag{
|
UnlockedAccountFlag = cli.StringFlag{
|
||||||
Name: "unlock",
|
Name: "unlock",
|
||||||
Usage: "Unlock a given account untill this programs exits (address:password)",
|
Usage: "unlock the account given until this program exits (prompts for password). '--unlock coinbase' unlocks the primary (coinbase) account",
|
||||||
|
Value: "",
|
||||||
|
}
|
||||||
|
PasswordFileFlag = cli.StringFlag{
|
||||||
|
Name: "password",
|
||||||
|
Usage: "Path to password file for (un)locking an existing account.",
|
||||||
|
Value: "",
|
||||||
}
|
}
|
||||||
|
|
||||||
// logging and debug settings
|
// logging and debug settings
|
||||||
@ -243,12 +244,7 @@ func GetChain(ctx *cli.Context) (*core.ChainManager, common.Database, common.Dat
|
|||||||
|
|
||||||
func GetAccountManager(ctx *cli.Context) *accounts.Manager {
|
func GetAccountManager(ctx *cli.Context) *accounts.Manager {
|
||||||
dataDir := ctx.GlobalString(DataDirFlag.Name)
|
dataDir := ctx.GlobalString(DataDirFlag.Name)
|
||||||
var ks crypto.KeyStore2
|
ks := crypto.NewKeyStorePassphrase(path.Join(dataDir, "keys"))
|
||||||
if ctx.GlobalBool(UnencryptedKeysFlag.Name) {
|
|
||||||
ks = crypto.NewKeyStorePlain(path.Join(dataDir, "plainkeys"))
|
|
||||||
} else {
|
|
||||||
ks = crypto.NewKeyStorePassphrase(path.Join(dataDir, "keys"))
|
|
||||||
}
|
|
||||||
return accounts.NewManager(ks)
|
return accounts.NewManager(ks)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,7 +2,6 @@ package common
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
|
||||||
"os"
|
"os"
|
||||||
"os/user"
|
"os/user"
|
||||||
"path"
|
"path"
|
||||||
@ -43,35 +42,6 @@ func FileExist(filePath string) bool {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
func ReadAllFile(filePath string) (string, error) {
|
|
||||||
file, err := os.Open(filePath)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
data, err := ioutil.ReadAll(file)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
return string(data), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func WriteFile(filePath string, content []byte) error {
|
|
||||||
fh, err := os.OpenFile(filePath, os.O_TRUNC|os.O_RDWR|os.O_CREATE, os.ModePerm)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer fh.Close()
|
|
||||||
|
|
||||||
_, err = fh.Write(content)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func AbsolutePath(Datadir string, filename string) string {
|
func AbsolutePath(Datadir string, filename string) string {
|
||||||
if path.IsAbs(filename) {
|
if path.IsAbs(filename) {
|
||||||
return filename
|
return filename
|
||||||
|
@ -2,56 +2,11 @@ package common
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"os"
|
"os"
|
||||||
"testing"
|
// "testing"
|
||||||
|
|
||||||
checker "gopkg.in/check.v1"
|
checker "gopkg.in/check.v1"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestGoodFile(t *testing.T) {
|
|
||||||
goodpath := "~/goethereumtest.pass"
|
|
||||||
path := ExpandHomePath(goodpath)
|
|
||||||
contentstring := "3.14159265358979323846"
|
|
||||||
|
|
||||||
err := WriteFile(path, []byte(contentstring))
|
|
||||||
if err != nil {
|
|
||||||
t.Error("Could not write file")
|
|
||||||
}
|
|
||||||
|
|
||||||
if !FileExist(path) {
|
|
||||||
t.Error("File not found at", path)
|
|
||||||
}
|
|
||||||
|
|
||||||
v, err := ReadAllFile(path)
|
|
||||||
if err != nil {
|
|
||||||
t.Error("Could not read file", path)
|
|
||||||
}
|
|
||||||
if v != contentstring {
|
|
||||||
t.Error("Expected", contentstring, "Got", v)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestBadFile(t *testing.T) {
|
|
||||||
badpath := "/this/path/should/not/exist/goethereumtest.fail"
|
|
||||||
path := ExpandHomePath(badpath)
|
|
||||||
contentstring := "3.14159265358979323846"
|
|
||||||
|
|
||||||
err := WriteFile(path, []byte(contentstring))
|
|
||||||
if err == nil {
|
|
||||||
t.Error("Wrote file, but should not be able to", path)
|
|
||||||
}
|
|
||||||
|
|
||||||
if FileExist(path) {
|
|
||||||
t.Error("Found file, but should not be able to", path)
|
|
||||||
}
|
|
||||||
|
|
||||||
v, err := ReadAllFile(path)
|
|
||||||
if err == nil {
|
|
||||||
t.Error("Read file, but should not be able to", v)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
type CommonSuite struct{}
|
type CommonSuite struct{}
|
||||||
|
|
||||||
var _ = checker.Suite(&CommonSuite{})
|
var _ = checker.Suite(&CommonSuite{})
|
||||||
|
@ -4,8 +4,8 @@ import (
|
|||||||
"math"
|
"math"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
|
||||||
"github.com/ethereum/go-ethereum/core/state"
|
"github.com/ethereum/go-ethereum/core/state"
|
||||||
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
type AccountChange struct {
|
type AccountChange struct {
|
||||||
|
@ -5,6 +5,8 @@ import (
|
|||||||
"math/big"
|
"math/big"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const maxStack = 1024
|
||||||
|
|
||||||
func newStack() *stack {
|
func newStack() *stack {
|
||||||
return &stack{}
|
return &stack{}
|
||||||
}
|
}
|
||||||
@ -15,6 +17,10 @@ type stack struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (st *stack) push(d *big.Int) {
|
func (st *stack) push(d *big.Int) {
|
||||||
|
if len(st.data) == maxStack {
|
||||||
|
panic(fmt.Sprintf("stack limit reached (%d)", maxStack))
|
||||||
|
}
|
||||||
|
|
||||||
stackItem := new(big.Int).Set(d)
|
stackItem := new(big.Int).Set(d)
|
||||||
if len(st.data) > st.ptr {
|
if len(st.data) > st.ptr {
|
||||||
st.data[st.ptr] = stackItem
|
st.data[st.ptr] = stackItem
|
||||||
|
@ -9,6 +9,7 @@ import (
|
|||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
@ -139,6 +140,12 @@ func LoadECDSA(file string) (*ecdsa.PrivateKey, error) {
|
|||||||
return ToECDSA(buf), nil
|
return ToECDSA(buf), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SaveECDSA saves a secp256k1 private key to the given file with restrictive
|
||||||
|
// permissions
|
||||||
|
func SaveECDSA(file string, key *ecdsa.PrivateKey) error {
|
||||||
|
return ioutil.WriteFile(file, FromECDSA(key), 0600)
|
||||||
|
}
|
||||||
|
|
||||||
func GenerateKey() (*ecdsa.PrivateKey, error) {
|
func GenerateKey() (*ecdsa.PrivateKey, error) {
|
||||||
return ecdsa.GenerateKey(S256(), rand.Reader)
|
return ecdsa.GenerateKey(S256(), rand.Reader)
|
||||||
}
|
}
|
||||||
|
@ -85,6 +85,16 @@ func (k *Key) UnmarshalJSON(j []byte) (err error) {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func NewKeyFromECDSA(privateKeyECDSA *ecdsa.PrivateKey) *Key {
|
||||||
|
id := uuid.NewRandom()
|
||||||
|
key := &Key{
|
||||||
|
Id: id,
|
||||||
|
Address: PubkeyToAddress(privateKeyECDSA.PublicKey),
|
||||||
|
PrivateKey: privateKeyECDSA,
|
||||||
|
}
|
||||||
|
return key
|
||||||
|
}
|
||||||
|
|
||||||
func NewKey(rand io.Reader) *Key {
|
func NewKey(rand io.Reader) *Key {
|
||||||
randBytes := make([]byte, 64)
|
randBytes := make([]byte, 64)
|
||||||
_, err := rand.Read(randBytes)
|
_, err := rand.Read(randBytes)
|
||||||
@ -97,11 +107,5 @@ func NewKey(rand io.Reader) *Key {
|
|||||||
panic("key generation: ecdsa.GenerateKey failed: " + err.Error())
|
panic("key generation: ecdsa.GenerateKey failed: " + err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
id := uuid.NewRandom()
|
return NewKeyFromECDSA(privateKeyECDSA)
|
||||||
key := &Key{
|
|
||||||
Id: id,
|
|
||||||
Address: PubkeyToAddress(privateKeyECDSA.PublicKey),
|
|
||||||
PrivateKey: privateKeyECDSA,
|
|
||||||
}
|
|
||||||
return key
|
|
||||||
}
|
}
|
||||||
|
File diff suppressed because one or more lines are too long
@ -2,9 +2,9 @@ package jsre
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/robertkrimen/otto"
|
"github.com/robertkrimen/otto"
|
||||||
|
"io/ioutil"
|
||||||
|
"os"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type testNativeObjectBinding struct {
|
type testNativeObjectBinding struct {
|
||||||
@ -26,7 +26,7 @@ func (no *testNativeObjectBinding) TestMethod(call otto.FunctionCall) otto.Value
|
|||||||
func TestExec(t *testing.T) {
|
func TestExec(t *testing.T) {
|
||||||
jsre := New("/tmp")
|
jsre := New("/tmp")
|
||||||
|
|
||||||
common.WriteFile("/tmp/test.js", []byte(`msg = "testMsg"`))
|
ioutil.WriteFile("/tmp/test.js", []byte(`msg = "testMsg"`), os.ModePerm)
|
||||||
err := jsre.Exec("test.js")
|
err := jsre.Exec("test.js")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("expected no error, got %v", err)
|
t.Errorf("expected no error, got %v", err)
|
||||||
@ -64,7 +64,7 @@ func TestBind(t *testing.T) {
|
|||||||
func TestLoadScript(t *testing.T) {
|
func TestLoadScript(t *testing.T) {
|
||||||
jsre := New("/tmp")
|
jsre := New("/tmp")
|
||||||
|
|
||||||
common.WriteFile("/tmp/test.js", []byte(`msg = "testMsg"`))
|
ioutil.WriteFile("/tmp/test.js", []byte(`msg = "testMsg"`), os.ModePerm)
|
||||||
_, err := jsre.Run(`loadScript("test.js")`)
|
_, err := jsre.Run(`loadScript("test.js")`)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("expected no error, got %v", err)
|
t.Errorf("expected no error, got %v", err)
|
||||||
|
@ -1,12 +1,15 @@
|
|||||||
package miner
|
package miner
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"sync"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
"github.com/ethereum/go-ethereum/pow"
|
"github.com/ethereum/go-ethereum/pow"
|
||||||
)
|
)
|
||||||
|
|
||||||
type CpuMiner struct {
|
type CpuMiner struct {
|
||||||
|
chMu sync.Mutex
|
||||||
c chan *types.Block
|
c chan *types.Block
|
||||||
quit chan struct{}
|
quit chan struct{}
|
||||||
quitCurrentOp chan struct{}
|
quitCurrentOp chan struct{}
|
||||||
@ -43,16 +46,13 @@ func (self *CpuMiner) Start() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (self *CpuMiner) update() {
|
func (self *CpuMiner) update() {
|
||||||
justStarted := true
|
|
||||||
out:
|
out:
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
case block := <-self.c:
|
case block := <-self.c:
|
||||||
if justStarted {
|
self.chMu.Lock()
|
||||||
justStarted = true
|
|
||||||
} else {
|
|
||||||
self.quitCurrentOp <- struct{}{}
|
self.quitCurrentOp <- struct{}{}
|
||||||
}
|
self.chMu.Unlock()
|
||||||
|
|
||||||
go self.mine(block)
|
go self.mine(block)
|
||||||
case <-self.quit:
|
case <-self.quit:
|
||||||
@ -60,6 +60,7 @@ out:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
close(self.quitCurrentOp)
|
||||||
done:
|
done:
|
||||||
// Empty channel
|
// Empty channel
|
||||||
for {
|
for {
|
||||||
@ -75,12 +76,20 @@ done:
|
|||||||
|
|
||||||
func (self *CpuMiner) mine(block *types.Block) {
|
func (self *CpuMiner) mine(block *types.Block) {
|
||||||
minerlogger.Debugf("(re)started agent[%d]. mining...\n", self.index)
|
minerlogger.Debugf("(re)started agent[%d]. mining...\n", self.index)
|
||||||
|
|
||||||
|
// Reset the channel
|
||||||
|
self.chMu.Lock()
|
||||||
|
self.quitCurrentOp = make(chan struct{}, 1)
|
||||||
|
self.chMu.Unlock()
|
||||||
|
|
||||||
|
// Mine
|
||||||
nonce, mixDigest, _ := self.pow.Search(block, self.quitCurrentOp)
|
nonce, mixDigest, _ := self.pow.Search(block, self.quitCurrentOp)
|
||||||
if nonce != 0 {
|
if nonce != 0 {
|
||||||
block.SetNonce(nonce)
|
block.SetNonce(nonce)
|
||||||
block.Header().MixDigest = common.BytesToHash(mixDigest)
|
block.Header().MixDigest = common.BytesToHash(mixDigest)
|
||||||
self.returnCh <- block
|
self.returnCh <- block
|
||||||
//self.returnCh <- Work{block.Number().Uint64(), nonce, mixDigest, seedHash}
|
} else {
|
||||||
|
self.returnCh <- nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -50,6 +50,7 @@ out:
|
|||||||
break out
|
break out
|
||||||
case work := <-a.workCh:
|
case work := <-a.workCh:
|
||||||
a.work = work
|
a.work = work
|
||||||
|
a.returnCh <- nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,7 @@ import (
|
|||||||
"math/big"
|
"math/big"
|
||||||
"sort"
|
"sort"
|
||||||
"sync"
|
"sync"
|
||||||
|
"sync/atomic"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
@ -59,12 +60,13 @@ type Agent interface {
|
|||||||
|
|
||||||
type worker struct {
|
type worker struct {
|
||||||
mu sync.Mutex
|
mu sync.Mutex
|
||||||
|
|
||||||
agents []Agent
|
agents []Agent
|
||||||
recv chan *types.Block
|
recv chan *types.Block
|
||||||
mux *event.TypeMux
|
mux *event.TypeMux
|
||||||
quit chan struct{}
|
quit chan struct{}
|
||||||
pow pow.PoW
|
pow pow.PoW
|
||||||
atWork int
|
atWork int64
|
||||||
|
|
||||||
eth core.Backend
|
eth core.Backend
|
||||||
chain *core.ChainManager
|
chain *core.ChainManager
|
||||||
@ -107,7 +109,7 @@ func (self *worker) start() {
|
|||||||
|
|
||||||
func (self *worker) stop() {
|
func (self *worker) stop() {
|
||||||
self.mining = false
|
self.mining = false
|
||||||
self.atWork = 0
|
atomic.StoreInt64(&self.atWork, 0)
|
||||||
|
|
||||||
close(self.quit)
|
close(self.quit)
|
||||||
}
|
}
|
||||||
@ -135,9 +137,6 @@ out:
|
|||||||
self.uncleMu.Unlock()
|
self.uncleMu.Unlock()
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.atWork == 0 {
|
|
||||||
self.commitNewWork()
|
|
||||||
}
|
|
||||||
case <-self.quit:
|
case <-self.quit:
|
||||||
// stop all agents
|
// stop all agents
|
||||||
for _, agent := range self.agents {
|
for _, agent := range self.agents {
|
||||||
@ -146,6 +145,11 @@ out:
|
|||||||
break out
|
break out
|
||||||
case <-timer.C:
|
case <-timer.C:
|
||||||
minerlogger.Infoln("Hash rate:", self.HashRate(), "Khash")
|
minerlogger.Infoln("Hash rate:", self.HashRate(), "Khash")
|
||||||
|
|
||||||
|
// XXX In case all mined a possible uncle
|
||||||
|
if atomic.LoadInt64(&self.atWork) == 0 {
|
||||||
|
self.commitNewWork()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -155,6 +159,12 @@ out:
|
|||||||
func (self *worker) wait() {
|
func (self *worker) wait() {
|
||||||
for {
|
for {
|
||||||
for block := range self.recv {
|
for block := range self.recv {
|
||||||
|
atomic.AddInt64(&self.atWork, -1)
|
||||||
|
|
||||||
|
if block == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
if err := self.chain.InsertChain(types.Blocks{block}); err == nil {
|
if err := self.chain.InsertChain(types.Blocks{block}); err == nil {
|
||||||
for _, uncle := range block.Uncles() {
|
for _, uncle := range block.Uncles() {
|
||||||
delete(self.possibleUncles, uncle.Hash())
|
delete(self.possibleUncles, uncle.Hash())
|
||||||
@ -170,7 +180,6 @@ func (self *worker) wait() {
|
|||||||
} else {
|
} else {
|
||||||
self.commitNewWork()
|
self.commitNewWork()
|
||||||
}
|
}
|
||||||
self.atWork--
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -182,8 +191,9 @@ func (self *worker) push() {
|
|||||||
|
|
||||||
// push new work to agents
|
// push new work to agents
|
||||||
for _, agent := range self.agents {
|
for _, agent := range self.agents {
|
||||||
|
atomic.AddInt64(&self.atWork, 1)
|
||||||
|
|
||||||
agent.Work() <- self.current.block.Copy()
|
agent.Work() <- self.current.block.Copy()
|
||||||
self.atWork++
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
31
rpc/args.go
31
rpc/args.go
@ -3,6 +3,8 @@ package rpc
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
// "errors"
|
||||||
|
// "fmt"
|
||||||
"math/big"
|
"math/big"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
@ -60,6 +62,26 @@ func numString(raw interface{}, number *int64) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// func toNumber(v interface{}) (int64, error) {
|
||||||
|
// var str string
|
||||||
|
// if v != nil {
|
||||||
|
// var ok bool
|
||||||
|
// str, ok = v.(string)
|
||||||
|
// if !ok {
|
||||||
|
// return 0, errors.New("is not a string or undefined")
|
||||||
|
// }
|
||||||
|
// } else {
|
||||||
|
// str = "latest"
|
||||||
|
// }
|
||||||
|
|
||||||
|
// switch str {
|
||||||
|
// case "latest":
|
||||||
|
// return -1, nil
|
||||||
|
// default:
|
||||||
|
// return int64(common.Big(v.(string)).Int64()), nil
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
type GetBlockByHashArgs struct {
|
type GetBlockByHashArgs struct {
|
||||||
BlockHash string
|
BlockHash string
|
||||||
IncludeTxs bool
|
IncludeTxs bool
|
||||||
@ -442,6 +464,14 @@ func (args *BlockFilterArgs) UnmarshalJSON(b []byte) (err error) {
|
|||||||
return NewInsufficientParamsError(len(obj), 1)
|
return NewInsufficientParamsError(len(obj), 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// args.Earliest, err = toNumber(obj[0].ToBlock)
|
||||||
|
// if err != nil {
|
||||||
|
// return NewDecodeParamError(fmt.Sprintf("FromBlock %v", err))
|
||||||
|
// }
|
||||||
|
// args.Latest, err = toNumber(obj[0].FromBlock)
|
||||||
|
// if err != nil {
|
||||||
|
// return NewDecodeParamError(fmt.Sprintf("ToBlock %v", err))
|
||||||
|
|
||||||
var num int64
|
var num int64
|
||||||
if err := blockHeight(obj[0].FromBlock, &num); err != nil {
|
if err := blockHeight(obj[0].FromBlock, &num); err != nil {
|
||||||
return err
|
return err
|
||||||
@ -464,6 +494,7 @@ func (args *BlockFilterArgs) UnmarshalJSON(b []byte) (err error) {
|
|||||||
|
|
||||||
if err := numString(obj[0].Offset, &num); err != nil {
|
if err := numString(obj[0].Offset, &num); err != nil {
|
||||||
return err
|
return err
|
||||||
|
|
||||||
}
|
}
|
||||||
args.Skip = int(num)
|
args.Skip = int(num)
|
||||||
|
|
||||||
|
@ -9,5 +9,16 @@
|
|||||||
"full_size": 1073739904,
|
"full_size": 1073739904,
|
||||||
"header_hash": "2a8de2adf89af77358250bf908bf04ba94a6e8c3ba87775564a41d269a05e4ce",
|
"header_hash": "2a8de2adf89af77358250bf908bf04ba94a6e8c3ba87775564a41d269a05e4ce",
|
||||||
"cache_hash": "35ded12eecf2ce2e8da2e15c06d463aae9b84cb2530a00b932e4bbc484cde353"
|
"cache_hash": "35ded12eecf2ce2e8da2e15c06d463aae9b84cb2530a00b932e4bbc484cde353"
|
||||||
|
},
|
||||||
|
"second": {
|
||||||
|
"nonce": "307692cf71b12f6d",
|
||||||
|
"mixhash": "e55d02c555a7969361cf74a9ec6211d8c14e4517930a00442f171bdb1698d175",
|
||||||
|
"header": "f901f7a01bef91439a3e070a6586851c11e6fd79bbbea074b2b836727b8e75c7d4a6b698a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794ea3cb5f94fa2ddd52ec6dd6eb75cf824f4058ca1a00c6e51346be0670ce63ac5f05324e27d20b180146269c5aab844d09a2b108c64a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008302004002832fefd880845511ed2a80a0e55d02c555a7969361cf74a9ec6211d8c14e4517930a00442f171bdb1698d17588307692cf71b12f6d",
|
||||||
|
"seed": "0000000000000000000000000000000000000000000000000000000000000000",
|
||||||
|
"result": "ab9b13423cface72cbec8424221651bc2e384ef0f7a560e038fc68c8d8684829",
|
||||||
|
"cache_size": 16776896,
|
||||||
|
"full_size": 1073739904,
|
||||||
|
"header_hash": "100cbec5e5ef82991290d0d93d758f19082e71f234cf479192a8b94df6da6bfe",
|
||||||
|
"cache_hash": "35ded12eecf2ce2e8da2e15c06d463aae9b84cb2530a00b932e4bbc484cde353"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user