diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS
new file mode 100644
index 000000000..6076fe46a
--- /dev/null
+++ b/.github/CODEOWNERS
@@ -0,0 +1,9 @@
+# Lines starting with '#' are comments.
+# Each line is a file pattern followed by one or more owners.
+
+accounts/usbwallet @karalabe
+consensus @karalabe
+core/ @karalabe @holiman
+eth/ @karalabe
+mobile/ @karalabe
+p2p/ @fjl @zsfelfoldi
diff --git a/.gitignore b/.gitignore
index b6c7fd1ef..2a86d1822 100644
--- a/.gitignore
+++ b/.gitignore
@@ -39,3 +39,6 @@ profile.cov
/dashboard/assets/node_modules
/dashboard/assets/stats.json
/dashboard/assets/public/bundle.js
+
+# git merge
+*.orig
diff --git a/README.md b/README.md
index d86a0d926..652b16edd 100644
--- a/README.md
+++ b/README.md
@@ -261,7 +261,7 @@ instance for mining, run it with all your usual flags, extended by:
$ gmc --mine --minerthreads=1 --etherbase=0x0000000000000000000000000000000000000000
```
-Which will start mining bocks and transactions on a single CPU thread, crediting all proceedings to
+Which will start mining blocks and transactions on a single CPU thread, crediting all proceedings to
the account specified by `--etherbase`. You can further tune the mining by changing the default gas
limit blocks converge to (`--targetgaslimit`) and the price transactions are accepted at (`--gasprice`).
diff --git a/VERSION b/VERSION
index 7ec1d6db4..aedc15bb0 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-2.1.0
+2.5.3
diff --git a/accounts/keystore/account_cache.go b/accounts/keystore/account_cache.go
index 4b08cc202..71f698ece 100644
--- a/accounts/keystore/account_cache.go
+++ b/accounts/keystore/account_cache.go
@@ -20,7 +20,6 @@ import (
"bufio"
"encoding/json"
"fmt"
- "io/ioutil"
"os"
"path/filepath"
"sort"
@@ -75,13 +74,6 @@ type accountCache struct {
fileC fileCache
}
-// fileCache is a cache of files seen during scan of keystore
-type fileCache struct {
- all *set.SetNonTS // list of all files
- mtime time.Time // latest mtime seen
- mu sync.RWMutex
-}
-
func newAccountCache(keydir string) (*accountCache, chan struct{}) {
ac := &accountCache{
keydir: keydir,
@@ -236,66 +228,22 @@ func (ac *accountCache) close() {
ac.mu.Unlock()
}
-// scanFiles performs a new scan on the given directory, compares against the already
-// cached filenames, and returns file sets: new, missing , modified
-func (fc *fileCache) scanFiles(keyDir string) (set.Interface, set.Interface, set.Interface, error) {
- t0 := time.Now()
- files, err := ioutil.ReadDir(keyDir)
- t1 := time.Now()
- if err != nil {
- return nil, nil, nil, err
- }
- fc.mu.RLock()
- prevMtime := fc.mtime
- fc.mu.RUnlock()
-
- filesNow := set.NewNonTS()
- moddedFiles := set.NewNonTS()
- var newMtime time.Time
- for _, fi := range files {
- modTime := fi.ModTime()
- path := filepath.Join(keyDir, fi.Name())
- if skipKeyFile(fi) {
- log.Trace("Ignoring file on account scan", "path", path)
- continue
- }
- filesNow.Add(path)
- if modTime.After(prevMtime) {
- moddedFiles.Add(path)
- }
- if modTime.After(newMtime) {
- newMtime = modTime
- }
- }
- t2 := time.Now()
-
- fc.mu.Lock()
- // Missing = previous - current
- missing := set.Difference(fc.all, filesNow)
- // New = current - previous
- newFiles := set.Difference(filesNow, fc.all)
- // Modified = modified - new
- modified := set.Difference(moddedFiles, newFiles)
- fc.all = filesNow
- fc.mtime = newMtime
- fc.mu.Unlock()
- t3 := time.Now()
- log.Debug("FS scan times", "list", t1.Sub(t0), "set", t2.Sub(t1), "diff", t3.Sub(t2))
- return newFiles, missing, modified, nil
-}
-
// scanAccounts checks if any changes have occurred on the filesystem, and
// updates the account cache accordingly
func (ac *accountCache) scanAccounts() error {
- newFiles, missingFiles, modified, err := ac.fileC.scanFiles(ac.keydir)
- t1 := time.Now()
+ // Scan the entire folder metadata for file changes
+ creates, deletes, updates, err := ac.fileC.scan(ac.keydir)
if err != nil {
log.Debug("Failed to reload keystore contents", "err", err)
return err
}
+ if creates.Size() == 0 && deletes.Size() == 0 && updates.Size() == 0 {
+ return nil
+ }
+ // Create a helper method to scan the contents of the key files
var (
- buf = new(bufio.Reader)
- keyJSON struct {
+ buf = new(bufio.Reader)
+ key struct {
Address string `json:"address"`
}
)
@@ -308,9 +256,9 @@ func (ac *accountCache) scanAccounts() error {
defer fd.Close()
buf.Reset(fd)
// Parse the address.
- keyJSON.Address = ""
- err = json.NewDecoder(buf).Decode(&keyJSON)
- addr := common.HexToAddress(keyJSON.Address)
+ key.Address = ""
+ err = json.NewDecoder(buf).Decode(&key)
+ addr := common.HexToAddress(key.Address)
switch {
case err != nil:
log.Debug("Failed to decode keystore key", "path", path, "err", err)
@@ -321,47 +269,30 @@ func (ac *accountCache) scanAccounts() error {
}
return nil
}
+ // Process all the file diffs
+ start := time.Now()
- for _, p := range newFiles.List() {
- path, _ := p.(string)
- a := readAccount(path)
- if a != nil {
+ for _, p := range creates.List() {
+ if a := readAccount(p.(string)); a != nil {
ac.add(*a)
}
}
- for _, p := range missingFiles.List() {
- path, _ := p.(string)
- ac.deleteByFile(path)
+ for _, p := range deletes.List() {
+ ac.deleteByFile(p.(string))
}
-
- for _, p := range modified.List() {
- path, _ := p.(string)
- a := readAccount(path)
+ for _, p := range updates.List() {
+ path := p.(string)
ac.deleteByFile(path)
- if a != nil {
+ if a := readAccount(path); a != nil {
ac.add(*a)
}
}
-
- t2 := time.Now()
+ end := time.Now()
select {
case ac.notify <- struct{}{}:
default:
}
- log.Trace("Handled keystore changes", "time", t2.Sub(t1))
-
+ log.Trace("Handled keystore changes", "time", end.Sub(start))
return nil
}
-
-func skipKeyFile(fi os.FileInfo) bool {
- // Skip editor backups and UNIX-style hidden files.
- if strings.HasSuffix(fi.Name(), "~") || strings.HasPrefix(fi.Name(), ".") {
- return true
- }
- // Skip misc special files, directories (yes, symlinks too).
- if fi.IsDir() || fi.Mode()&os.ModeType != 0 {
- return true
- }
- return false
-}
diff --git a/accounts/keystore/account_cache_test.go b/accounts/keystore/account_cache_test.go
index e3dc31065..fe9233c04 100644
--- a/accounts/keystore/account_cache_test.go
+++ b/accounts/keystore/account_cache_test.go
@@ -59,7 +59,7 @@ func TestWatchNewFile(t *testing.T) {
// Ensure the watcher is started before adding any files.
ks.Accounts()
- time.Sleep(200 * time.Millisecond)
+ time.Sleep(1000 * time.Millisecond)
// Move in the files.
wantAccounts := make([]accounts.Account, len(cachetestAccounts))
@@ -349,6 +349,9 @@ func TestUpdatedKeyfileContents(t *testing.T) {
return
}
+ // needed so that modTime of `file` is different to its current value after forceCopyFile
+ time.Sleep(1000 * time.Millisecond)
+
// Now replace file contents
if err := forceCopyFile(file, cachetestAccounts[1].URL.Path); err != nil {
t.Fatal(err)
@@ -362,6 +365,9 @@ func TestUpdatedKeyfileContents(t *testing.T) {
return
}
+ // needed so that modTime of `file` is different to its current value after forceCopyFile
+ time.Sleep(1000 * time.Millisecond)
+
// Now replace file contents again
if err := forceCopyFile(file, cachetestAccounts[2].URL.Path); err != nil {
t.Fatal(err)
@@ -374,6 +380,10 @@ func TestUpdatedKeyfileContents(t *testing.T) {
t.Error(err)
return
}
+
+ // needed so that modTime of `file` is different to its current value after ioutil.WriteFile
+ time.Sleep(1000 * time.Millisecond)
+
// Now replace file contents with crap
if err := ioutil.WriteFile(file, []byte("foo"), 0644); err != nil {
t.Fatal(err)
diff --git a/accounts/keystore/file_cache.go b/accounts/keystore/file_cache.go
new file mode 100644
index 000000000..c91b7b7b6
--- /dev/null
+++ b/accounts/keystore/file_cache.go
@@ -0,0 +1,102 @@
+// Copyright 2017 The go-ethereum Authors
+// This file is part of the go-ethereum library.
+//
+// The go-ethereum library is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// The go-ethereum library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with the go-ethereum library. If not, see .
+
+package keystore
+
+import (
+ "io/ioutil"
+ "os"
+ "path/filepath"
+ "strings"
+ "sync"
+ "time"
+
+ "github.com/ethereum/go-ethereum/log"
+ set "gopkg.in/fatih/set.v0"
+)
+
+// fileCache is a cache of files seen during scan of keystore.
+type fileCache struct {
+ all *set.SetNonTS // Set of all files from the keystore folder
+ lastMod time.Time // Last time instance when a file was modified
+ mu sync.RWMutex
+}
+
+// scan performs a new scan on the given directory, compares against the already
+// cached filenames, and returns file sets: creates, deletes, updates.
+func (fc *fileCache) scan(keyDir string) (set.Interface, set.Interface, set.Interface, error) {
+ t0 := time.Now()
+
+ // List all the failes from the keystore folder
+ files, err := ioutil.ReadDir(keyDir)
+ if err != nil {
+ return nil, nil, nil, err
+ }
+ t1 := time.Now()
+
+ fc.mu.Lock()
+ defer fc.mu.Unlock()
+
+ // Iterate all the files and gather their metadata
+ all := set.NewNonTS()
+ mods := set.NewNonTS()
+
+ var newLastMod time.Time
+ for _, fi := range files {
+ // Skip any non-key files from the folder
+ path := filepath.Join(keyDir, fi.Name())
+ if skipKeyFile(fi) {
+ log.Trace("Ignoring file on account scan", "path", path)
+ continue
+ }
+ // Gather the set of all and fresly modified files
+ all.Add(path)
+
+ modified := fi.ModTime()
+ if modified.After(fc.lastMod) {
+ mods.Add(path)
+ }
+ if modified.After(newLastMod) {
+ newLastMod = modified
+ }
+ }
+ t2 := time.Now()
+
+ // Update the tracked files and return the three sets
+ deletes := set.Difference(fc.all, all) // Deletes = previous - current
+ creates := set.Difference(all, fc.all) // Creates = current - previous
+ updates := set.Difference(mods, creates) // Updates = modified - creates
+
+ fc.all, fc.lastMod = all, newLastMod
+ t3 := time.Now()
+
+ // Report on the scanning stats and return
+ log.Debug("FS scan times", "list", t1.Sub(t0), "set", t2.Sub(t1), "diff", t3.Sub(t2))
+ return creates, deletes, updates, nil
+}
+
+// skipKeyFile ignores editor backups, hidden files and folders/symlinks.
+func skipKeyFile(fi os.FileInfo) bool {
+ // Skip editor backups and UNIX-style hidden files.
+ if strings.HasSuffix(fi.Name(), "~") || strings.HasPrefix(fi.Name(), ".") {
+ return true
+ }
+ // Skip misc special files, directories (yes, symlinks too).
+ if fi.IsDir() || fi.Mode()&os.ModeType != 0 {
+ return true
+ }
+ return false
+}
diff --git a/accounts/keystore/keystore_passphrase.go b/accounts/keystore/keystore_passphrase.go
index 535608a60..eaec39f7d 100644
--- a/accounts/keystore/keystore_passphrase.go
+++ b/accounts/keystore/keystore_passphrase.go
@@ -28,6 +28,7 @@ package keystore
import (
"bytes"
"crypto/aes"
+ crand "crypto/rand"
"crypto/sha256"
"encoding/hex"
"encoding/json"
@@ -90,6 +91,12 @@ func (ks keyStorePassphrase) GetKey(addr common.Address, filename, auth string)
return key, nil
}
+// StoreKey generates a key, encrypts with 'auth' and stores in the given directory
+func StoreKey(dir, auth string, scryptN, scryptP int) (common.Address, error) {
+ _, a, err := storeNewKey(&keyStorePassphrase{dir, scryptN, scryptP}, crand.Reader, auth)
+ return a.Address, err
+}
+
func (ks keyStorePassphrase) StoreKey(filename string, key *Key, auth string) error {
keyjson, err := EncryptKey(key, auth, ks.scryptN, ks.scryptP)
if err != nil {
diff --git a/accounts/keystore/watch.go b/accounts/keystore/watch.go
index 602300b10..bbcfb9925 100644
--- a/accounts/keystore/watch.go
+++ b/accounts/keystore/watch.go
@@ -81,10 +81,14 @@ func (w *watcher) loop() {
// When an event occurs, the reload call is delayed a bit so that
// multiple events arriving quickly only cause a single reload.
var (
- debounce = time.NewTimer(0)
debounceDuration = 500 * time.Millisecond
rescanTriggered = false
+ debounce = time.NewTimer(0)
)
+ // Ignore initial trigger
+ if !debounce.Stop() {
+ <-debounce.C
+ }
defer debounce.Stop()
for {
select {
diff --git a/accounts/manager.go b/accounts/manager.go
index 78ddb1368..96ca298fc 100644
--- a/accounts/manager.go
+++ b/accounts/manager.go
@@ -41,6 +41,11 @@ type Manager struct {
// NewManager creates a generic account manager to sign transaction via various
// supported backends.
func NewManager(backends ...Backend) *Manager {
+ // Retrieve the initial list of wallets from the backends and sort by URL
+ var wallets []Wallet
+ for _, backend := range backends {
+ wallets = merge(wallets, backend.Wallets()...)
+ }
// Subscribe to wallet notifications from all backends
updates := make(chan WalletEvent, 4*len(backends))
@@ -48,11 +53,6 @@ func NewManager(backends ...Backend) *Manager {
for i, backend := range backends {
subs[i] = backend.Subscribe(updates)
}
- // Retrieve the initial list of wallets from the backends and sort by URL
- var wallets []Wallet
- for _, backend := range backends {
- wallets = merge(wallets, backend.Wallets()...)
- }
// Assemble the account manager and return
am := &Manager{
backends: make(map[reflect.Type][]Backend),
diff --git a/build/ci.go b/build/ci.go
index ed63058d8..1aaa094c0 100644
--- a/build/ci.go
+++ b/build/ci.go
@@ -199,7 +199,7 @@ func doInstall(cmdline []string) {
build.MustRun(goinstall)
return
}
- // If we are cross compiling to ARMv5 ARMv6 or ARMv7, clean any prvious builds
+ // If we are cross compiling to ARMv5 ARMv6 or ARMv7, clean any previous builds
if *arch == "arm" {
os.RemoveAll(filepath.Join(runtime.GOROOT(), "pkg", runtime.GOOS+"_arm"))
for _, path := range filepath.SplitList(build.GOPATH()) {
diff --git a/cmd/faucet/faucet.go b/cmd/faucet/faucet.go
index e43980e63..9c813ee1a 100644
--- a/cmd/faucet/faucet.go
+++ b/cmd/faucet/faucet.go
@@ -83,7 +83,8 @@ var (
captchaToken = flag.String("captcha.token", "", "Recaptcha site key to authenticate client side")
captchaSecret = flag.String("captcha.secret", "", "Recaptcha secret key to authenticate server side")
- logFlag = flag.Int("loglevel", 3, "Log level to use for Ethereum and the faucet")
+ noauthFlag = flag.Bool("noauth", false, "Enables funding requests without authentication")
+ logFlag = flag.Int("loglevel", 3, "Log level to use for Ethereum and the faucet")
)
var (
@@ -132,6 +133,7 @@ func main() {
"Amounts": amounts,
"Periods": periods,
"Recaptcha": *captchaToken,
+ "NoAuth": *noauthFlag,
})
if err != nil {
log.Crit("Failed to render the faucet template", "err", err)
@@ -374,7 +376,7 @@ func (f *faucet) apiHandler(conn *websocket.Conn) {
if err = websocket.JSON.Receive(conn, &msg); err != nil {
return
}
- if !strings.HasPrefix(msg.URL, "https://gist.github.com/") && !strings.HasPrefix(msg.URL, "https://twitter.com/") &&
+ if !*noauthFlag && !strings.HasPrefix(msg.URL, "https://gist.github.com/") && !strings.HasPrefix(msg.URL, "https://twitter.com/") &&
!strings.HasPrefix(msg.URL, "https://plus.google.com/") && !strings.HasPrefix(msg.URL, "https://www.facebook.com/") {
if err = sendError(conn, errors.New("URL doesn't link to supported services")); err != nil {
log.Warn("Failed to send URL error to client", "err", err)
@@ -435,13 +437,19 @@ func (f *faucet) apiHandler(conn *websocket.Conn) {
)
switch {
case strings.HasPrefix(msg.URL, "https://gist.github.com/"):
- username, avatar, address, err = authGitHub(msg.URL)
+ if err = sendError(conn, errors.New("GitHub authentication discontinued at the official request of GitHub")); err != nil {
+ log.Warn("Failed to send GitHub deprecation to client", "err", err)
+ return
+ }
+ continue
case strings.HasPrefix(msg.URL, "https://twitter.com/"):
username, avatar, address, err = authTwitter(msg.URL)
case strings.HasPrefix(msg.URL, "https://plus.google.com/"):
username, avatar, address, err = authGooglePlus(msg.URL)
case strings.HasPrefix(msg.URL, "https://www.facebook.com/"):
username, avatar, address, err = authFacebook(msg.URL)
+ case *noauthFlag:
+ username, avatar, address, err = authNoAuth(msg.URL)
default:
err = errors.New("Something funky happened, please open an issue at https://github.com/ethereum/go-ethereum/issues")
}
@@ -776,3 +784,14 @@ func authFacebook(url string) (string, string, common.Address, error) {
}
return username + "@facebook", avatar, address, nil
}
+
+// authNoAuth tries to interpret a faucet request as a plain Ethereum address,
+// without actually performing any remote authentication. This mode is prone to
+// Byzantine attack, so only ever use for truly private networks.
+func authNoAuth(url string) (string, string, common.Address, error) {
+ address := common.HexToAddress(regexp.MustCompile("0x[0-9a-fA-F]{40}").FindString(url))
+ if address == (common.Address{}) {
+ return "", "", common.Address{}, errors.New("No Ethereum address found to fund")
+ }
+ return address.Hex() + "@noauth", "", address, nil
+}
diff --git a/cmd/faucet/faucet.html b/cmd/faucet/faucet.html
index 5d3b8741b..ab41b2c87 100644
--- a/cmd/faucet/faucet.html
+++ b/cmd/faucet/faucet.html
@@ -80,11 +80,8 @@
{{
How does this work?
-
This Ether faucet is running on the {{.Network}} network. To prevent malicious actors from exhausting all available funds or accumulating enough Ether to mount long running spam attacks, requests are tied to certain common 3rd party accounts. Anyone having a GitHub, Twitter, Google+ or Facebook account may request funds within the permitted limits.
+
This Ether faucet is running on the {{.Network}} network. To prevent malicious actors from exhausting all available funds or accumulating enough Ether to mount long running spam attacks, requests are tied to common 3rd party social network accounts. Anyone having a Twitter, Google+ or Facebook account may request funds within the permitted limits.
-
-
To request funds via GitHub, create a gist with your Ethereum address embedded into the content (the file name doesn't matter). Copy-paste the gists URL into the above input box and fire away!
-
To request funds via Twitter, make a tweet with your Ethereum address pasted into the contents (surrounding text doesn't matter). Copy-paste the tweets URL into the above input box and fire away!
@@ -93,6 +90,11 @@
How does this work?
To request funds via Facebook, publish a new public post with your Ethereum address embedded into the content (surrounding text doesn't matter). Copy-paste the posts URL into the above input box and fire away!
+
+ {{if .NoAuth}}
+
+
To request funds without authentication, simply copy-paste your Ethereum address into the above input box (surrounding text doesn't matter) and fire away. This mode is susceptible to Byzantine attacks. Only use for debugging or private networks!
+ {{end}}
You can track the current pending requests below the input field to see how much you have to wait until your turn comes.
{{if .Recaptcha}}The faucet is running invisible reCaptcha protection against bots.{{end}}
@@ -126,12 +128,7 @@
How does this work?
};
// Define a method to reconnect upon server loss
var reconnect = function() {
- if (attempt % 2 == 0) {
- server = new WebSocket("wss://" + location.host + "/api");
- } else {
- server = new WebSocket("ws://" + location.host + "/api");
- }
- attempt++;
+ server = new WebSocket(((window.location.protocol === "https:") ? "wss://" : "ws://") + window.location.host + "/api");
server.onmessage = function(event) {
var msg = JSON.parse(event.data);
diff --git a/cmd/faucet/website.go b/cmd/faucet/website.go
index 6a99f8c6f..7936b158e 100644
--- a/cmd/faucet/website.go
+++ b/cmd/faucet/website.go
@@ -68,7 +68,7 @@ func (fi bindataFileInfo) Sys() interface{} {
return nil
}
-var _faucetHtml = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xcc\x3a\x7f\x73\xdb\xb6\x92\x7f\x3b\x9f\x62\xcb\x8b\x9f\xa4\xb3\x48\xca\x76\x92\xe7\x93\x48\x75\x72\x79\x7d\x7d\xb9\xb9\xeb\xeb\xb4\xe9\xdc\xbd\x69\x3b\x37\x20\xb1\x12\x11\x83\x00\x0b\x80\x92\x55\x8f\xbe\xfb\x0d\x00\x92\xa2\x7e\xd8\x71\x9a\xdc\x5d\xfc\x87\x4c\x00\x8b\xdd\xc5\xfe\xc6\x92\xc9\x57\x7f\xf9\xfb\x9b\x77\xff\xf8\xfe\x1b\x28\x4c\xc9\xe7\xcf\x12\xfb\x0f\x38\x11\xcb\x34\x40\x11\xcc\x9f\x9d\x25\x05\x12\x3a\x7f\x76\x76\x96\x94\x68\x08\xe4\x05\x51\x1a\x4d\x1a\xd4\x66\x11\xde\x04\xbb\x85\xc2\x98\x2a\xc4\xdf\x6a\xb6\x4a\x83\xff\x0a\x7f\x7a\x1d\xbe\x91\x65\x45\x0c\xcb\x38\x06\x90\x4b\x61\x50\x98\x34\x78\xfb\x4d\x8a\x74\x89\xbd\x7d\x82\x94\x98\x06\x2b\x86\xeb\x4a\x2a\xd3\x03\x5d\x33\x6a\x8a\x94\xe2\x8a\xe5\x18\xba\xc1\x18\x98\x60\x86\x11\x1e\xea\x9c\x70\x4c\x2f\x83\xf9\x33\x8b\xc7\x30\xc3\x71\x7e\x7f\x1f\x7d\x87\x66\x2d\xd5\xed\x76\x3b\x85\xd7\xb5\x29\x50\x18\x96\x13\x83\x14\xfe\x4a\xea\x1c\x4d\x12\x7b\x48\xb7\x89\x33\x71\x0b\x85\xc2\x45\x1a\x58\xd6\xf5\x34\x8e\x73\x2a\xde\xeb\x28\xe7\xb2\xa6\x0b\x4e\x14\x46\xb9\x2c\x63\xf2\x9e\xdc\xc5\x9c\x65\x3a\x36\x6b\x66\x0c\xaa\x30\x93\xd2\x68\xa3\x48\x15\x5f\x47\xd7\xd1\x9f\xe3\x5c\xeb\xb8\x9b\x8b\x4a\x26\xa2\x5c\xeb\x00\x14\xf2\x34\xd0\x66\xc3\x51\x17\x88\x26\x80\x78\xfe\xc7\xe8\x2e\xa4\x30\x21\x59\xa3\x96\x25\xc6\x2f\xa2\x3f\x47\x13\x47\xb2\x3f\xfd\x38\x55\x4b\x56\xe7\x8a\x55\x06\xb4\xca\x9f\x4c\xf7\xfd\x6f\x35\xaa\x4d\x7c\x1d\x5d\x46\x97\xcd\xc0\xd1\x79\xaf\x83\x79\x12\x7b\x84\xf3\x4f\xc2\x1d\x0a\x69\x36\xf1\x55\xf4\x22\xba\x8c\x2b\x92\xdf\x92\x25\xd2\x96\x92\x5d\x8a\xda\xc9\xcf\x46\xf7\x21\x1d\xbe\x3f\x54\xe1\xe7\x20\x56\xca\x12\x85\x89\xde\xeb\xf8\x2a\xba\xbc\x89\x26\xed\xc4\x31\x7e\x47\xc0\x2a\xcd\x92\x3a\x8b\x56\xa8\xac\xe5\xf2\x30\x47\x61\x50\xc1\xbd\x9d\x3d\x2b\x99\x08\x0b\x64\xcb\xc2\x4c\xe1\x72\x32\x39\x9f\x9d\x9a\x5d\x15\x7e\x9a\x32\x5d\x71\xb2\x99\xc2\x82\xe3\x9d\x9f\x22\x9c\x2d\x45\xc8\x0c\x96\x7a\x0a\x1e\xb3\x5b\xd8\x3a\x9a\x95\x92\x4b\x85\x5a\x37\xc4\x2a\xa9\x99\x61\x52\x4c\xad\x45\x11\xc3\x56\x78\x0a\x56\x57\x44\x1c\x6d\x20\x99\x96\xbc\x36\x78\xc0\x48\xc6\x65\x7e\xeb\xe7\x9c\x37\xf7\x0f\x91\x4b\x2e\xd5\x14\xd6\x05\x6b\xb6\x81\x23\x04\x95\xc2\x06\x3d\x54\x84\x52\x26\x96\x53\x78\x55\x35\xe7\x81\x92\xa8\x25\x13\x53\x98\xec\xb6\x24\x71\x2b\xc6\x24\xf6\x81\xeb\xd9\x59\x92\x49\xba\x71\x3a\xa4\x6c\x05\x39\x27\x5a\xa7\xc1\x81\x88\x5d\x40\xda\x03\xb0\x71\x88\x30\xd1\x2e\xed\xad\x29\xb9\x0e\xc0\x11\x4a\x03\xcf\x44\x98\x49\x63\x64\x39\x85\x4b\xcb\x5e\xb3\xe5\x00\x1f\x0f\xf9\x32\xbc\xbc\x6a\x17\xcf\x92\xe2\xb2\x45\x62\xf0\xce\x84\x4e\x3f\x9d\x66\x82\x79\xc2\xda\xbd\x0b\x02\x0b\x12\x66\xc4\x14\x01\x10\xc5\x48\x58\x30\x4a\x51\xa4\x81\x51\x35\x5a\x3b\x62\x73\xe8\x87\xbf\x07\xa2\x5f\x71\xd9\xf2\x15\x53\xb6\x6a\x8e\xd5\x7b\x3c\x38\xe1\xc3\x87\xb8\x81\xe6\x41\x2e\x16\x1a\x4d\xd8\x3b\x53\x0f\x98\x89\xaa\x36\xe1\x52\xc9\xba\xea\xd6\xcf\x12\x37\x0b\x8c\xa6\x41\xad\x78\xd0\x84\x7f\xf7\x68\x36\x55\x23\x8a\xa0\x3b\xb8\x54\x65\x68\x35\xa1\x24\x0f\xa0\xe2\x24\xc7\x42\x72\x8a\x2a\x0d\x7e\x94\x39\x23\x1c\x84\x3f\x33\xfc\xf4\xc3\xbf\x43\xa3\x32\x26\x96\xb0\x91\xb5\x82\x6f\x4c\x81\x0a\xeb\x12\x08\xa5\xd6\x5c\xa3\x28\xea\x31\xe2\x6c\xf7\x98\xd5\x30\x33\x62\x07\x75\x96\x64\xb5\x31\xb2\x03\xcc\x8c\x80\xcc\x88\x90\xe2\x82\xd4\xdc\x00\x55\xb2\xa2\x72\x2d\x42\x23\x97\x4b\x9b\xe9\xfc\x21\xfc\xa6\x00\x28\x31\xa4\x59\x4a\x83\x16\xb6\xd5\x21\xd1\x95\xac\xea\xaa\xd1\xa2\x9f\xc4\xbb\x8a\x08\x8a\xd4\xea\x9c\x6b\x0c\xe6\xdf\xb2\x15\x42\x89\xfe\x2c\x67\x87\x26\x91\x13\x85\x26\xec\x23\x3d\x32\x8c\x24\xf6\xcc\xf8\x23\x41\xf3\x97\xd4\xbc\xc5\xd4\x1d\xa1\x44\x51\xc3\xde\x28\x54\x36\xae\x04\xf3\xfb\x7b\x45\xc4\x12\xe1\x39\xa3\x77\x63\x78\x4e\x4a\x59\x0b\x03\xd3\x14\xa2\xd7\xee\x51\x6f\xb7\x7b\xd8\x01\x12\xce\xe6\x09\x79\xcc\xbc\x41\x8a\x9c\xb3\xfc\x36\x0d\x0c\x43\x95\xde\xdf\x5b\xe4\xdb\xed\x0c\xee\xef\xd9\x02\x9e\x47\x3f\x60\x4e\x2a\x93\x17\x64\xbb\x5d\xaa\xf6\x39\xc2\x3b\xcc\x6b\x83\xc3\xd1\xfd\x3d\x72\x8d\xdb\xad\xae\xb3\x92\x99\x61\xbb\xdd\xce\x0b\xba\xdd\x5a\x9e\x1b\x3e\xb7\x5b\x88\x2d\x52\x41\xf1\x0e\x9e\x47\xdf\xa3\x62\x92\x6a\xf0\xf0\x49\x4c\xe6\x49\xcc\xd9\xbc\xd9\xb7\x2f\xa4\xb8\xe6\x3b\x7b\x89\xad\xc1\x74\x76\xee\xdc\xc6\xb1\xda\xe7\xf4\x84\x17\x2c\xc3\x8e\xfb\xc6\x1e\x34\x33\x78\x8b\x9b\x34\xb8\xbf\xef\xef\x6d\x56\x73\xc2\x79\x46\xac\x5c\xfc\xd1\xba\x4d\xbf\xa3\xb5\xd3\x15\xd3\xae\xa4\x9a\xb7\x1c\xec\xd8\x7e\xa2\x5b\x1f\x04\x2e\x23\xab\x29\x5c\x5f\xf5\xa2\xd6\x29\x8f\x7f\x75\xe0\xf1\xd7\x27\x81\x2b\x22\x90\x83\xfb\x0d\x75\x49\x78\xfb\xdc\x78\x4b\xcf\xf9\x0e\x37\x85\x36\x46\x77\xac\x75\xb1\x7e\x32\x03\xb9\x42\xb5\xe0\x72\x3d\x05\x52\x1b\x39\x83\x92\xdc\x75\xf9\xee\x7a\x32\xe9\xf3\x6d\x4b\x41\x92\x71\x74\xd1\x45\xe1\x6f\x35\x6a\xa3\xbb\x58\xe2\x97\xdc\xaf\x0d\x29\x14\x85\x46\x7a\x20\x0d\x4b\xd1\x8a\xd6\x41\xf5\x54\xdf\x09\xf3\x24\xef\x0b\x29\xbb\x14\xd2\x67\xa3\x41\xdd\xcb\x76\xc1\x3c\x31\x6a\x07\x77\x96\x18\xfa\x51\x29\x40\xd9\x12\xef\xa1\x0c\xe0\x23\x9a\x3d\x7b\x85\xa8\x7c\x7d\x61\x4d\x16\xdc\x30\x89\x0d\xfd\x04\xca\xd6\x08\x33\xa2\xf1\x29\xe4\x5d\xa6\xdf\x91\x77\xc3\x4f\xa5\x5f\x20\x51\x26\x43\x62\x9e\xc2\xc0\xa2\x16\xb4\x77\x7e\x17\x3b\x3f\x95\x81\x5a\xb0\x15\x2a\xcd\xcc\xe6\xa9\x1c\x20\xdd\xb1\xe0\xc7\xfb\x2c\x24\xb1\x51\x8f\xdb\x5a\x7f\xf0\x99\x9c\xfb\x43\x25\xc9\xf5\xfc\x6f\x72\x0d\x54\xa2\x06\x53\x30\x0d\x36\xb9\x7e\x9d\xc4\xc5\x75\x07\x52\xcd\xdf\xd9\x05\x27\x54\x58\xb8\xd2\x02\x98\x06\x55\x0b\x97\x79\xa5\x00\x53\xe0\x7e\x39\xd2\x24\xe9\x08\xde\x49\x5b\xd2\xad\x50\x18\x28\x09\x67\x39\x93\xb5\x06\x92\x1b\xa9\x34\x2c\x94\x2c\x01\xef\x0a\x52\x6b\x63\x11\xd9\xf0\x41\x56\x84\x71\xe7\x4b\x4e\xa5\x20\x15\x90\x3c\xaf\xcb\xda\x96\xa4\x62\x09\x28\x64\xbd\x2c\x1a\x5e\x8c\x04\x9f\x98\xb8\x14\xcb\x8e\x1f\x5d\x91\x12\x88\x31\x24\xbf\xd5\x63\x68\xa3\x02\x10\x85\x60\x18\x52\xbb\x2b\x47\x65\xeb\x06\xc8\x65\x59\x4a\x01\xd7\x8a\x42\x45\x94\xd9\x58\x5a\x2e\xbd\x45\xf0\x5a\x6c\xa4\x40\x28\xc8\xca\xb1\x06\xdf\x32\xf3\xb7\x3a\x1b\xc3\x3b\x7f\x9f\x18\xc3\xb7\x52\x2e\x39\x5e\x58\x0e\xff\x4a\x72\xcc\xa4\xbc\x6d\xb7\x43\x49\x36\x2d\xe1\xe6\x1c\x6b\x66\x0a\xe6\x05\x55\xa1\x2a\x2d\x0e\x0a\x9c\x95\xcc\xe8\x28\x89\xab\x5d\x6c\xdd\x65\x69\x1e\x16\x52\xb1\xdf\x6d\x89\xc3\x3b\x7d\x01\x24\xd4\x1c\xc4\x99\x36\x4c\x3a\x03\xe0\xb8\x30\x53\x78\xe1\xc3\xe4\xa1\x49\x2f\x99\x29\xea\x2c\x24\xfc\xa4\x53\xb5\x68\xdd\x3d\xd3\xa6\x9f\x29\x5c\xfb\xe2\xd6\x97\x15\xd4\xf4\x42\x22\x3d\x30\x3c\x4f\xf7\xe6\xa6\xba\xeb\x58\xe9\x2a\xe4\x49\x87\xc4\xda\xc3\xbe\x60\x56\x6c\x27\xdb\x5c\x21\x31\x08\x04\x12\x72\x70\x61\x5e\x32\x6d\x22\xcf\xbd\xbb\x72\x05\x60\x88\x5a\xa2\x49\x83\xff\x26\x99\xac\xcd\x34\xe3\x44\xdc\x06\x73\x0b\x67\x33\xbc\x93\xf7\xe9\x9a\x10\xb0\xcc\x90\x52\xa4\xc0\x84\x91\x4e\x23\x4d\x07\x02\x86\x76\xb0\x60\x1c\x5d\x91\xea\x7c\x42\x0c\xac\x36\xad\xc6\x47\x51\x92\xa9\x78\xfe\x46\x56\x9b\xb0\x22\xda\xa0\xdb\x6a\x09\x6a\x57\x8b\x76\xd8\x48\x26\x57\x08\xbe\xea\xcd\xe4\x1d\x10\x41\x61\xc1\x14\x02\x59\x93\xcd\x57\x49\x4c\xdd\x1d\xa5\x95\xe3\x1f\x57\x66\x73\xb3\xfd\xa2\x34\xd9\x79\x47\x49\x6e\x4f\x2a\xb2\x61\xda\x29\x91\x39\xa9\xc7\x66\x8d\x68\xbe\xb6\x21\x39\xfd\xc1\x23\x64\x62\x79\x7e\x35\xf1\x91\xc6\x3e\x58\xf4\xe7\x57\x13\x2b\xe1\xf3\xab\xc9\xe4\x6e\xf2\xc4\xbf\xf3\xab\x89\x14\xe7\x57\x13\x53\xe0\xf9\xd5\xe4\xfc\xea\xba\x1f\xa3\xfc\x4c\x6b\x1d\x16\x0a\xb5\xa5\xd6\x86\xae\x87\x4c\xcc\xb1\xfb\x21\x1b\x73\x06\x72\x6c\x61\x1a\x86\xba\x56\x4a\xd6\xc2\x56\x3b\x60\xcf\xfc\x24\x2b\x3b\x12\xa3\xae\xab\x4a\x2a\x13\xf5\xc5\x49\xec\xfd\x96\xa3\x8e\x6f\x26\x2f\x6f\x5e\x3d\xca\xbe\xb3\x58\x77\x86\xff\x73\xab\x5d\xba\xb0\x19\x56\xbc\xd6\xb6\xb4\x64\xf6\x4e\xf7\x45\x99\xb0\x8f\xeb\xf0\x3d\xaf\xf5\x18\xaa\x3a\xe3\x4c\x17\x40\x40\xe0\x1a\x12\x6d\x94\x14\xcb\xb9\x9b\xcd\x93\xb8\x19\x42\x25\xb5\xf9\x83\x11\xe7\x0f\x99\x83\xa5\xf7\xff\x14\x74\x16\x4d\xaa\xfb\xa2\x54\xd6\xe6\xdf\x2f\x55\x5f\x47\xee\xbb\x5e\xaf\xa3\x56\x92\xce\x77\x0b\xe4\x55\x6c\xab\x91\x5a\x30\xb3\x89\x7d\x14\x94\x22\xfe\x9a\xd1\xf4\xea\xe6\xea\xd5\xab\xab\x17\xff\x72\xf3\xf2\xe5\xd5\xcd\x8b\x97\x0f\x39\x76\x67\x14\x1f\xef\xd7\x5d\xed\xc9\x7b\x35\xdf\x3f\x64\x0d\x39\x11\x60\x14\xc9\x6f\xbd\x10\x6a\xa5\xac\x10\x2a\xf4\xe7\xef\x4a\xab\x0c\xb9\x5c\x3b\x10\x4f\x67\xc1\x90\xbb\x3a\x4b\x23\x42\x21\xd7\x50\xd6\xb9\x93\xb5\x2d\xa7\xd0\x2e\xac\x09\x33\x50\x0b\xc3\xb8\x57\x81\xa9\x95\xab\xc6\x70\xaf\x1a\x3a\xba\x6d\x27\x58\xce\xdf\xd9\x1c\x7d\x54\x84\x76\xf7\x64\x50\xf8\xc6\x83\x43\xa5\xa4\xc1\xdc\xca\x11\xc8\x92\x30\xa1\xad\x04\x5c\xbd\x85\xe5\x13\xee\xd1\xdd\x53\xf3\xb0\xeb\x09\xbb\xe5\x38\x86\x6f\xb9\xcc\x08\x87\x95\x75\x85\x8c\xdb\x02\x5a\x42\x21\xed\xd1\x7b\xd2\xd2\x86\x98\x5a\x83\x5c\xb8\x59\xcf\xb9\xdd\xbf\x22\xca\x56\xa9\x58\x56\x06\xd2\xa6\xa3\x69\xe7\x34\xaa\x55\xd3\xa7\xb5\x43\xc3\x50\xed\xad\x77\x52\x4f\xe1\xe7\x5f\x67\xcf\x1a\x56\xfe\x82\x0b\x26\x6c\xc6\x5d\xd4\xc2\x1f\xd9\x14\xc4\x34\x15\x95\x86\x9c\x4b\x5d\x2b\xcf\x21\x55\xb2\x02\xcb\x65\x8b\xa9\xc5\x6c\x17\x2a\x47\xad\x45\x32\x2c\x88\x2e\x46\x4d\x43\x56\xa1\xd3\x52\xb7\xd6\xce\x9f\x2d\xa4\x82\xa1\x45\xc0\xd2\xc9\x0c\x58\xd2\xe2\x8d\x38\x8a\xa5\x29\x66\xc0\x2e\x2e\x3a\xe0\x33\xb6\x80\x61\x0b\xf1\x33\xfb\x35\x32\x77\x91\xa5\x02\x69\x0a\x7d\x6a\x8e\x60\x83\x47\x57\x9c\xe5\x38\x64\x63\xb8\x1c\xcd\xda\xd5\x4c\x21\xb9\x6d\x47\x8d\x1e\xfd\x3f\xf7\xbb\x9d\xed\x4b\xc6\x09\x7f\x4f\x36\xbe\xdb\xa2\x81\xb8\x22\x0e\x6a\xc5\xa1\xf1\x19\xaf\x82\x4e\x21\x0e\xae\x2f\x95\x23\xbb\x6c\x1e\x1a\x9b\x6a\x8f\xe0\xd1\x44\x1a\x05\x1d\xfe\xdb\x8f\x7f\xff\x2e\xd2\x46\x31\xb1\x64\x8b\xcd\xf0\xbe\x56\x7c\x0a\xcf\x87\xc1\x3f\xd5\x8a\x07\xa3\x9f\x27\xbf\x46\x2b\xc2\x6b\x1c\x3b\x7d\x4f\xdd\xef\x11\x95\x31\x34\x8f\x53\xd8\x27\xb8\x1d\x8d\x66\xa7\x3b\x53\xbd\x46\x9a\x42\x8d\x66\x68\x01\x3b\xc3\x3f\x94\x11\x81\x12\x4d\x21\x9d\xeb\x2a\xcc\xa5\x10\x98\x1b\xa8\x2b\x29\x1a\x91\x00\x97\x5a\xef\x0c\xb1\x85\x48\x8f\x8d\xc2\x6a\xb9\xb5\xee\x73\xb8\xb2\xda\x9d\x74\xaa\x6d\x90\xa5\x2e\x48\xff\x27\x66\x3f\xca\xfc\x16\xcd\x30\x58\x6b\x1b\x1c\x03\xb8\x00\x2e\x73\x62\xf1\x45\x85\x0d\xd5\x17\x10\xc4\xa4\x62\x41\xa3\xfc\x2d\x20\xd7\xf8\x61\x64\x4f\xc2\xe5\x5f\x94\x78\x4e\x2f\x2e\xbc\x3f\xb5\x9a\x93\xa2\x44\xad\xc9\x12\xfb\x27\x74\x97\xd9\xee\x28\x56\x10\xa5\x5e\x42\x0a\x4e\xc3\x15\x51\x1a\x3d\x48\x44\x89\x21\xad\xb9\x5a\x71\x38\xb0\x34\x05\x51\x73\xbe\xb3\x72\xef\x55\xb3\xd6\x7e\xf7\xc0\x23\x9f\xe2\xbe\x4a\x53\xa8\x05\x75\x3a\xa2\xbb\x9d\xd6\x7a\x7c\xdf\x63\x14\xd9\x54\xb4\xdb\x31\x9a\xf5\xdd\x61\x0f\x1b\xd2\x0f\xa1\x43\x7a\x88\x0f\xe9\x03\x08\x5d\x9b\xe9\x31\x7c\xbe\x2d\xd5\x43\xe7\x26\x1e\xc0\x26\xea\x32\x43\xf5\x18\x3a\xdf\x66\x6a\xd0\x39\x51\xbf\x15\xa6\xb7\x77\x0c\x97\xaf\x46\x0f\x60\x47\xa5\xe4\x83\xc8\x85\x34\x9b\xe1\x3d\x27\x1b\x9b\x4f\x61\x60\x64\xf5\xc6\x75\x85\x06\x63\x97\xe4\xa7\xd0\x61\x18\xbb\x7e\xff\x14\x06\x6e\x64\xd7\x59\x89\x6e\xd7\xcb\xc9\x64\x32\x86\xf6\x45\xd9\xbf\x12\xeb\xc5\xaa\xc6\xed\x03\xfc\xe8\x3a\xcf\x6d\xad\xf1\x29\x1c\x35\x38\x3a\x9e\x9a\xf1\x27\x70\xd5\x25\x97\x3d\xb6\xe0\x4f\x7f\x82\xa3\xd5\x7d\x33\x8e\x63\xf8\x0f\xa2\x6e\x5d\x0f\xa7\x52\xb8\x72\x7d\x9e\x0e\xbe\x64\x5a\xbb\x36\x8a\x06\x2a\x05\x36\x7b\x3e\x2e\x6f\x1c\xf1\xd8\x80\xc1\x1c\x26\x87\x0c\xda\x78\xda\xcb\x2b\x27\xd2\x4d\x0f\xef\x7e\x26\x69\x25\x72\x22\x51\xb1\x12\xe1\xab\x14\x82\xa0\xbf\xf9\x08\xc2\x02\x74\xc8\xce\x34\x9a\x77\x5e\x17\xc3\x26\xbd\x9e\x4a\x7e\xa3\x31\x5c\x4f\x26\x93\xd1\x11\x13\xdb\x9d\x78\x5f\x57\xb6\xee\x02\x22\x36\x2e\xd2\x75\xb2\x75\x95\x9e\xad\xa1\x6c\x9c\xe3\x90\x4b\xce\x7d\xd1\xd3\x6c\xb5\x02\x6e\xfa\x5c\x29\x84\x97\xb3\x13\x69\xb8\x27\xc9\xde\xd1\x0e\xd5\x73\x42\xf6\x87\x2a\xda\x97\xd9\x01\x70\x78\xb9\xa7\x94\x3d\x7d\x9d\x56\xcc\x59\xc7\x37\xdb\x49\xf4\x40\x5d\x3b\x7d\x1d\xca\xac\xc7\xbf\xc7\x73\x71\xf9\xc4\x63\x74\xcb\x55\xad\x8b\xe1\x01\xa3\xa3\xd9\xb1\x6e\xde\x1a\x54\xc4\xa0\x7b\x75\xe1\x74\x81\xc2\xd8\x1a\xfb\x50\x25\xae\xfa\x56\x18\x2a\x14\x14\x55\x5b\x93\xf8\xcb\x84\xad\x20\xf7\x54\xe6\x6f\x1c\x7d\x73\xfa\x48\x87\x71\x35\x9d\x14\x08\x00\x70\xe0\x04\xce\x50\xf7\x2c\xd5\x02\x23\x27\x95\x46\x0a\x29\xf8\xef\x16\x86\xa3\xa8\x16\xec\x6e\x38\x0a\x9b\xf1\x21\x8e\x76\x7d\xd6\xdd\x2d\x5b\xb6\x2f\x52\x08\x12\xa3\x80\xd1\x74\x60\x93\xf0\xa9\x8a\xef\x02\x82\xc1\x7c\xc7\x41\x7f\x2b\x40\x62\xe8\xdc\xb5\xae\xfd\x35\xf1\x97\x20\x23\xf9\xed\xd2\xdd\xbd\xa6\xb6\x56\x1b\x1e\xa1\x25\x2b\x62\x88\x72\x58\x47\x33\xd8\x81\x37\x57\xd1\xdc\x2a\x67\x06\xfe\xc6\xeb\x3a\xe4\xd0\xbd\x55\x72\xa3\x4c\x2a\x8a\x2a\x54\x84\xb2\x5a\x4f\xe1\x45\x75\x37\xfb\xa5\x7d\xeb\xe6\xfa\xf8\x8f\xb2\x5a\x29\x9c\x1f\x71\xd4\xb4\x83\x2f\x20\x48\x62\x0b\xf0\x21\x34\xdd\x61\xfb\xdf\x4b\xc0\x89\xb7\x15\xd0\x7d\xcd\xd0\xcc\x97\x8c\x52\x8e\x96\xe1\x1d\x7a\xeb\x8c\x56\xff\x7d\x97\xda\x27\x09\xcd\x6b\x8a\xdd\x9e\xfd\xda\xea\xc4\x86\xee\x8d\xc7\xc0\x1a\x40\x68\x8f\xcc\x9c\xcc\x9b\x3e\x81\x9b\x56\x03\x27\x8b\xe6\xeb\x17\x5a\x2b\x57\x80\x0d\xc3\xc6\xc0\xc6\x30\xd0\xb6\x78\xa4\x7a\x30\x8a\x8a\xba\x24\x82\xfd\x8e\x43\x9b\x97\x46\x5e\x56\xee\x15\x4a\x70\x1c\x92\x8f\x98\xd9\xbd\xdb\x18\xb4\x39\x6e\xd0\x08\x71\xd0\x6a\xf7\xc5\xae\xa5\x30\x85\xc9\x6c\xf0\x91\x12\x3a\x4d\x25\xcc\x88\x82\xfe\x20\x6c\x93\x2f\x28\x69\xa9\xb7\x6b\x19\x51\x03\xdf\x2b\x71\x05\xbe\x90\xeb\x74\x70\x3d\xe9\x98\xf4\x8a\x76\x7a\x1e\x34\xb6\x76\xa4\x0c\xcb\x65\xeb\x9a\x73\xb8\x9e\x7c\x0e\x6e\x29\x11\x4b\x3c\x3c\x81\x51\xac\x42\x0a\x24\x37\x6c\x85\xff\x0b\x07\xf9\x0c\x42\xfe\x68\x16\xad\x1d\xb6\xc2\x73\x66\xba\xc7\xaf\x5d\xed\x64\xfb\xcf\xd6\xdf\x20\x76\x12\xbe\x80\xe0\xe4\x41\x1e\xb4\xc4\x03\xc0\x03\xd7\x7e\xd8\xef\xdd\x3b\xc1\xe0\x30\xa7\xd8\x6a\xb7\x7b\x9f\x3d\x8a\x0a\x53\xf2\x61\x90\x18\xf7\x5d\x93\xe5\xb9\xc3\xe0\x10\xf8\xe9\xfd\x92\x6e\xbb\x7f\x91\xc9\xb9\xd4\x78\x70\x51\x83\x5e\x71\xd2\x5d\xe6\xda\x4a\x04\xb6\xbb\xcf\xbf\xe2\x18\x7e\x34\x44\x19\x20\xf0\xd3\x5b\xa8\x2b\x4a\x8c\x7f\xfb\x66\xf3\xa3\xef\x48\xb6\xdf\x87\x65\x44\x69\x58\x48\xb5\x26\x8a\x36\x0d\x1e\x53\xe0\xc6\xbd\x7d\x6b\x4b\x3f\x8d\xe6\xad\x8d\x62\x2b\xc2\x87\x47\x17\xc7\xe7\xc3\x41\xd4\x57\xf9\x60\x14\x21\xc9\x8b\x63\x40\x97\xb1\x3a\xba\x29\x7c\xe7\xae\x00\xc3\xe7\x43\x53\x30\x3d\x8a\x88\x31\x6a\x38\xd8\x33\x86\xc1\xc8\xea\xf5\xb2\x77\x25\xeb\xb6\x27\x7b\x6e\xf5\x18\x8e\x5d\x31\xdd\x15\x02\x2d\x78\xae\xf5\xd0\xdb\xd5\x60\xdc\xc3\xbd\x6f\x56\x83\xf3\x41\xa7\xa8\x9d\x7b\xef\xce\x91\x9e\xe4\x64\x0f\xf5\xc0\x7a\xd9\xe0\x88\x3c\xa1\xf4\x8d\xf5\x9f\x61\x70\xc2\xd3\x0f\xad\x63\xd4\x09\xdb\xc7\xeb\x47\xa5\xec\xbf\xa4\x79\x40\xc4\x8c\x0e\x46\x91\xae\x33\xdf\xdc\x18\xbe\xec\x2e\x60\x2d\x98\x33\xde\xc3\x54\x70\x54\x50\x58\x12\xfb\x45\x45\x78\x50\x84\x3c\x92\x35\xda\xcb\xbc\x3b\xd5\x76\x6c\x05\x3e\x19\x75\xbd\xb1\x6f\xb4\x2d\xae\x7c\x5b\x78\x8d\x99\x76\x0d\x02\x68\xec\xdd\xb5\x83\x7c\xdb\xe7\xf5\xf7\x6f\x7b\xad\x9f\xce\x23\x86\x0e\x7b\xf7\xe9\xe6\xa9\x46\xcb\xc9\x6f\x45\xd7\xeb\x75\xe4\xdf\x76\xb8\x16\x6f\xd7\x89\x89\x49\xc5\xa2\xf7\x3a\x00\xa2\x37\x22\x07\x8a\x0b\x54\xf3\x1e\xfa\xa6\x3d\x93\xc4\xfe\x2b\xc6\x24\xf6\x1f\x6a\xff\x4f\x00\x00\x00\xff\xff\xf1\xa6\xb6\xb8\xb9\x2d\x00\x00")
+var _faucetHtml = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xcc\x5a\x71\x73\xdb\xb6\x92\xff\xdb\xf9\x14\x5b\x5e\xfc\x24\x9d\x4d\x52\xb6\x93\x3c\x9f\x44\xaa\x93\x97\xd7\xd7\xcb\xcd\x5d\xdb\x69\xd3\xb9\x7b\xd3\xd7\xb9\x01\x89\x95\x88\x18\x04\x58\x00\x94\xac\x7a\xf4\xdd\x6f\x00\x90\x14\x29\xc9\x6e\xd2\xe4\xde\x34\x7f\x38\x24\xb0\xd8\x5d\xec\xfe\x16\xbb\x58\x2a\xf9\xe2\xaf\xdf\xbe\x79\xf7\xf7\xef\xbe\x82\xc2\x94\x7c\xf1\x2c\xb1\xff\x01\x27\x62\x95\x06\x28\x82\xc5\xb3\xb3\xa4\x40\x42\x17\xcf\xce\xce\x92\x12\x0d\x81\xbc\x20\x4a\xa3\x49\x83\xda\x2c\xc3\xdb\x60\x3f\x51\x18\x53\x85\xf8\x4b\xcd\xd6\x69\xf0\x3f\xe1\x8f\xaf\xc3\x37\xb2\xac\x88\x61\x19\xc7\x00\x72\x29\x0c\x0a\x93\x06\x6f\xbf\x4a\x91\xae\xb0\xb7\x4e\x90\x12\xd3\x60\xcd\x70\x53\x49\x65\x7a\xa4\x1b\x46\x4d\x91\x52\x5c\xb3\x1c\x43\xf7\x72\x09\x4c\x30\xc3\x08\x0f\x75\x4e\x38\xa6\x57\xc1\xe2\x99\xe5\x63\x98\xe1\xb8\x78\x78\x88\xbe\x41\xb3\x91\xea\x6e\xb7\x9b\xc1\xeb\xda\x14\x28\x0c\xcb\x89\x41\x0a\x7f\x23\x75\x8e\x26\x89\x3d\xa5\x5b\xc4\x99\xb8\x83\x42\xe1\x32\x0d\xac\xea\x7a\x16\xc7\x39\x15\xef\x75\x94\x73\x59\xd3\x25\x27\x0a\xa3\x5c\x96\x31\x79\x4f\xee\x63\xce\x32\x1d\x9b\x0d\x33\x06\x55\x98\x49\x69\xb4\x51\xa4\x8a\x6f\xa2\x9b\xe8\xcf\x71\xae\x75\xdc\x8d\x45\x25\x13\x51\xae\x75\x00\x0a\x79\x1a\x68\xb3\xe5\xa8\x0b\x44\x13\x40\xbc\xf8\x7d\x72\x97\x52\x98\x90\x6c\x50\xcb\x12\xe3\x17\xd1\x9f\xa3\xa9\x13\xd9\x1f\x7e\x5a\xaa\x15\xab\x73\xc5\x2a\x03\x5a\xe5\x1f\x2c\xf7\xfd\x2f\x35\xaa\x6d\x7c\x13\x5d\x45\x57\xcd\x8b\x93\xf3\x5e\x07\x8b\x24\xf6\x0c\x17\x9f\xc4\x3b\x14\xd2\x6c\xe3\xeb\xe8\x45\x74\x15\x57\x24\xbf\x23\x2b\xa4\xad\x24\x3b\x15\xb5\x83\x9f\x4d\xee\x63\x3e\x7c\x7f\xe8\xc2\xcf\x21\xac\x94\x25\x0a\x13\xbd\xd7\xf1\x75\x74\x75\x1b\x4d\xdb\x81\x63\xfe\x4e\x80\x75\x9a\x15\x75\x16\xad\x51\x59\xe4\xf2\x30\x47\x61\x50\xc1\x83\x1d\x3d\x2b\x99\x08\x0b\x64\xab\xc2\xcc\xe0\x6a\x3a\x3d\x9f\x9f\x1a\x5d\x17\x7e\x98\x32\x5d\x71\xb2\x9d\xc1\x92\xe3\xbd\x1f\x22\x9c\xad\x44\xc8\x0c\x96\x7a\x06\x9e\xb3\x9b\xd8\x39\x99\x95\x92\x2b\x85\x5a\x37\xc2\x2a\xa9\x99\x61\x52\xcc\x2c\xa2\x88\x61\x6b\x3c\x45\xab\x2b\x22\x8e\x16\x90\x4c\x4b\x5e\x1b\x3c\x50\x24\xe3\x32\xbf\xf3\x63\x2e\x9a\xfb\x9b\xc8\x25\x97\x6a\x06\x9b\x82\x35\xcb\xc0\x09\x82\x4a\x61\xc3\x1e\x2a\x42\x29\x13\xab\x19\xbc\xaa\x9a\xfd\x40\x49\xd4\x8a\x89\x19\x4c\xf7\x4b\x92\xb8\x35\x63\x12\xfb\x83\xeb\xd9\x59\x92\x49\xba\x75\x3e\xa4\x6c\x0d\x39\x27\x5a\xa7\xc1\x81\x89\xdd\x81\x34\x20\xb0\xe7\x10\x61\xa2\x9d\x1a\xcc\x29\xb9\x09\xc0\x09\x4a\x03\xaf\x44\x98\x49\x63\x64\x39\x83\x2b\xab\x5e\xb3\xe4\x80\x1f\x0f\xf9\x2a\xbc\xba\x6e\x27\xcf\x92\xe2\xaa\x65\x62\xf0\xde\x84\xce\x3f\x9d\x67\x82\x45\xc2\xda\xb5\x4b\x02\x4b\x12\x66\xc4\x14\x01\x10\xc5\x48\x58\x30\x4a\x51\xa4\x81\x51\x35\x5a\x1c\xb1\x05\xf4\x8f\xbf\x47\x4e\xbf\xe2\xaa\xd5\x2b\xa6\x6c\xdd\x6c\xab\xf7\x78\xb0\xc3\xc7\x37\x71\x0b\xcd\x83\x5c\x2e\x35\x9a\xb0\xb7\xa7\x1e\x31\x13\x55\x6d\xc2\x95\x92\x75\xd5\xcd\x9f\x25\x6e\x14\x18\x4d\x83\x5a\xf1\xa0\x39\xfe\xdd\xa3\xd9\x56\x8d\x29\x82\x6e\xe3\x52\x95\xa1\xf5\x84\x92\x3c\x80\x8a\x93\x1c\x0b\xc9\x29\xaa\x34\xf8\x41\xe6\x8c\x70\x10\x7e\xcf\xf0\xe3\xf7\xff\x09\x8d\xcb\x98\x58\xc1\x56\xd6\x0a\xbe\x32\x05\x2a\xac\x4b\x20\x94\x5a\xb8\x46\x51\xd4\x53\xc4\x61\xf7\x58\xd5\x30\x33\x62\x4f\x75\x96\x64\xb5\x31\xb2\x23\xcc\x8c\x80\xcc\x88\x90\xe2\x92\xd4\xdc\x00\x55\xb2\xa2\x72\x23\x42\x23\x57\x2b\x9b\xe9\xfc\x26\xfc\xa2\x00\x28\x31\xa4\x99\x4a\x83\x96\xb6\xf5\x21\xd1\x95\xac\xea\xaa\xf1\xa2\x1f\xc4\xfb\x8a\x08\x8a\xd4\xfa\x9c\x6b\x0c\x16\x5f\xb3\x35\x42\x89\x7e\x2f\x67\x87\x90\xc8\x89\x42\x13\xf6\x99\x1e\x01\x23\x89\xbd\x32\x7e\x4b\xd0\xfc\x4b\x6a\xde\x72\xea\xb6\x50\xa2\xa8\x61\xf0\x16\x2a\x7b\xae\x04\x8b\x87\x07\x45\xc4\x0a\xe1\x39\xa3\xf7\x97\xf0\x9c\x94\xb2\x16\x06\x66\x29\x44\xaf\xdd\xa3\xde\xed\x06\xdc\x01\x12\xce\x16\x09\x79\x0a\xde\x20\x45\xce\x59\x7e\x97\x06\x86\xa1\x4a\x1f\x1e\x2c\xf3\xdd\x6e\x0e\x0f\x0f\x6c\x09\xcf\xa3\xef\x31\x27\x95\xc9\x0b\xb2\xdb\xad\x54\xfb\x1c\xe1\x3d\xe6\xb5\xc1\xf1\xe4\xe1\x01\xb9\xc6\xdd\x4e\xd7\x59\xc9\xcc\xb8\x5d\x6e\xc7\x05\xdd\xed\xac\xce\x8d\x9e\xbb\x1d\xc4\x96\xa9\xa0\x78\x0f\xcf\xa3\xef\x50\x31\x49\x35\x78\xfa\x24\x26\x8b\x24\xe6\x6c\xd1\xac\x1b\x1a\x29\xae\xf9\x1e\x2f\xb1\x05\x4c\x87\x73\x17\x36\x4e\xd5\xbe\xa6\x27\xa2\x60\x15\x76\xda\x37\x78\xd0\xcc\xe0\x1d\x6e\xd3\xe0\xe1\xa1\xbf\xb6\x99\xcd\x09\xe7\x19\xb1\x76\xf1\x5b\xeb\x16\xfd\x8a\x16\xa7\x6b\xa6\x5d\x49\xb5\x68\x35\xd8\xab\xfd\x81\x61\x7d\x70\x70\x19\x59\xcd\xe0\xe6\xba\x77\x6a\x9d\x8a\xf8\x57\x07\x11\x7f\x73\x92\xb8\x22\x02\x39\xb8\xbf\xa1\x2e\x09\x6f\x9f\x9b\x68\xe9\x05\xdf\xe1\xa2\xd0\x9e\xd1\x9d\x6a\xdd\x59\x3f\x9d\x83\x5c\xa3\x5a\x72\xb9\x99\x01\xa9\x8d\x9c\x43\x49\xee\xbb\x7c\x77\x33\x9d\xf6\xf5\xb6\xa5\x20\xc9\x38\xba\xd3\x45\xe1\x2f\x35\x6a\xa3\xbb\xb3\xc4\x4f\xb9\xbf\xf6\x48\xa1\x28\x34\xd2\x03\x6b\x58\x89\xd6\xb4\x8e\xaa\xe7\xfa\xce\x98\x27\x75\x5f\x4a\xd9\xa5\x90\xbe\x1a\x0d\xeb\x5e\xb6\x0b\x16\x89\x51\x7b\xba\xb3\xc4\xd0\x8f\x4a\x01\xca\x96\x78\x8f\x65\x00\x7f\xa2\xd9\xbd\x57\x88\xca\xd7\x17\x16\xb2\xe0\x5e\x93\xd8\xd0\x4f\x90\x6c\x41\x98\x11\x8d\x1f\x22\xde\x65\xfa\xbd\x78\xf7\xfa\xa9\xf2\x0b\x24\xca\x64\x48\xcc\x87\x28\xb0\xac\x05\xed\xed\xdf\x9d\x9d\x9f\xaa\x40\x2d\xd8\x1a\x95\x66\x66\xfb\xa1\x1a\x20\xdd\xab\xe0\xdf\x87\x2a\x24\xb1\x51\x4f\x63\xad\xff\xf2\x99\x82\xfb\xb7\x4a\x92\x9b\xc5\xbf\xcb\x0d\x50\x89\x1a\x4c\xc1\x34\xd8\xe4\xfa\x65\x12\x17\x37\x1d\x49\xb5\x78\x67\x27\x9c\x51\x61\xe9\x4a\x0b\x60\x1a\x54\x2d\x5c\xe6\x95\x02\x4c\x81\xc3\x72\xa4\x49\xd2\x11\xbc\x93\xb6\xa4\x5b\xa3\x30\x50\x12\xce\x72\x26\x6b\x0d\x24\x37\x52\x69\x58\x2a\x59\x02\xde\x17\xa4\xd6\xc6\x32\xb2\xc7\x07\x59\x13\xc6\x5d\x2c\x39\x97\x82\x54\x40\xf2\xbc\x2e\x6b\x5b\x92\x8a\x15\xa0\x90\xf5\xaa\x68\x74\x31\x12\x7c\x62\xe2\x52\xac\x3a\x7d\x74\x45\x4a\x20\xc6\x90\xfc\x4e\x5f\x42\x7b\x2a\x00\x51\x08\x86\x21\xb5\xab\x72\x59\x96\x52\xc0\x8d\xa2\x50\x11\x65\xb6\xa0\x87\xb5\x05\xc9\x73\x97\xe5\x22\x78\x2d\xb6\x52\x20\x14\x64\xed\x34\x84\x77\xfe\x3a\x71\x09\x5f\x4b\xb9\xe2\x78\x61\x15\xfc\x1b\xc9\x31\x93\xb2\x5b\x06\x25\xd9\xb6\x72\x9b\x6d\x6c\x98\x29\x98\xb7\x53\x85\xaa\xb4\x3c\x28\x70\x56\x32\xa3\xa3\x24\xae\xf6\x47\xeb\x3e\x49\xf3\xb0\x90\x8a\xfd\x6a\x2b\x1c\xde\x3f\x47\xcd\xc1\x29\xd3\x1e\x92\xce\xfd\x1c\x97\x66\x06\x2f\xfc\x21\x79\x08\xe8\xe6\x2a\x74\x0a\xcd\x2d\x4f\x77\xc5\xb4\x99\x67\x06\x37\xbe\xae\xf5\x15\x05\x35\x3d\x0d\xe8\x01\xe6\xbc\xd0\xdb\xdb\xea\xbe\xd3\xa3\x2b\x8e\xa7\x1d\x13\x0b\x85\xa1\x51\xd6\xac\x67\xcf\x92\xdc\x21\x10\x48\xc8\xc1\x55\xb9\x51\xda\x5d\xb4\x98\x6b\x14\xc4\x66\x83\x68\xbe\xb4\x31\x9c\x7e\xef\x19\x32\xb1\x3a\xbf\x9e\x7a\x68\xda\x07\xcb\xfe\xfc\x7a\xca\x84\x91\xe7\xd7\xd3\xe9\xfd\xf4\x03\xff\x9d\x5f\x4f\xa5\x38\xbf\x9e\x9a\x02\xcf\xaf\xa7\xe7\xd7\x37\x7d\x50\xfb\x91\xb6\xc4\xb4\x54\xa8\xad\xb4\x16\xeb\x01\x18\xa2\x56\x68\xd2\xe0\x7f\x49\x26\x6b\x33\xcb\x38\x11\x77\xc1\xc2\xa9\x6b\xcb\x0e\x87\x82\xd3\x85\x2a\x54\x44\x5b\x48\x58\x8d\x1d\x4a\x9a\xa6\x88\x86\xb1\xae\x95\x92\xb5\xb0\xe9\x11\xec\x9e\x5d\xa8\x8a\x91\x45\x99\x35\xcc\x24\x4a\x32\x15\x2f\xde\xc8\x6a\x1b\x3a\x26\x6e\xf9\x91\x19\x75\x5d\x55\x52\x99\xa8\x6f\x4e\x62\x2f\x44\x1c\x75\x7c\x3b\x7d\x79\xfb\xea\x49\xf5\xb5\x2d\xb7\xdd\x1e\x3a\x0d\x49\x26\xd7\x08\xbe\xb8\xcf\xe4\x3d\x10\x41\x61\xc9\x14\x02\xd9\x90\xed\x17\x49\x4c\xdd\x55\xec\xd3\x51\xbb\x72\x81\x16\x56\xbc\xd6\xb6\x16\x61\x36\x50\xff\x50\x10\xf6\x27\x01\x7c\xc7\x6b\x7d\x09\x55\x9d\x71\xa6\x0b\x20\x20\x70\x03\x89\x36\x4a\x8a\xd5\xc2\x8d\xe6\xf6\xaa\xea\x5e\xa1\x92\xda\x3c\x85\x06\x2c\x33\xa4\xf4\x04\x1e\x7e\x27\x1c\xac\x3c\xe7\xc2\x7f\xbe\xfb\x96\xcd\xe1\xf8\x87\x72\x59\x7b\x62\xff\x51\xfd\x75\x14\xbe\x9b\xcd\x26\x6a\x2d\xe9\x62\xb7\x40\x5e\xc5\x36\x8d\xd5\x82\x99\x6d\xec\x4f\x41\x29\xe2\x2f\x19\x4d\xaf\x6f\xaf\x5f\xbd\xba\x7e\xf1\x6f\xb7\x2f\x5f\x5e\xdf\xbe\x78\xf9\x58\x60\x77\xa0\xf8\xfd\x71\xed\xaf\x43\xdf\xc8\xd7\xb5\x29\xba\xbb\x90\xc7\x4b\x5b\x83\xdb\x4a\x8b\xda\xbb\xa4\x0a\x7e\x37\x86\x6a\x61\x0b\xca\x90\xf0\x93\xb5\xe0\x47\xa0\xc8\xc1\xe8\x09\xcd\x3e\x11\x5a\x2d\x7c\x2c\x52\x64\x6d\xec\x0e\xdb\xa6\x0c\x93\xa2\x83\xd3\x25\x68\x56\x56\x7c\x0b\xf9\xde\xeb\xa7\x71\xf5\xa8\x53\x7e\x13\x56\x43\xb7\x79\x90\xb9\x2a\xae\x94\x14\x6d\xf5\xa6\x6b\x9d\x63\xe5\xba\xf5\xb6\x22\xfa\xcb\xf6\x57\x22\x0c\x13\xd8\x56\x4e\x11\x7c\x2b\xf8\x16\x6a\x8d\xb0\x94\x0a\x28\x66\xf5\x6a\xe5\xca\x3d\x05\x95\x62\x6b\x62\xb0\x2d\x97\x74\x83\x8a\x0e\x14\xbd\x1b\xaa\x2d\x5d\x79\xaf\x92\xfc\xbb\xac\x21\x27\x02\x8c\x22\xf9\x9d\x8f\x94\x5a\x29\x1b\x29\x15\xfa\xdd\x74\x05\x5b\x86\x5c\x6e\x1c\x89\xdf\xf7\x92\x21\x77\xd5\x9b\x46\x84\x42\x6e\xa0\xac\x73\x17\x90\xb6\x3a\x73\x9b\xd8\x10\x66\xa0\x16\x86\x71\x6f\x4f\x53\x2b\x61\x6b\x3d\x1c\x14\x59\x47\x77\xf8\x04\xcb\xc5\xbb\x02\x4f\x94\xb6\xdd\xed\x1b\x14\xbe\xf1\xe4\x50\x29\x69\x30\xb7\x0e\x05\xb2\x22\x4c\x68\xeb\x11\x57\xc6\x61\xf9\x01\xb7\xf3\xee\xa9\x79\xd8\x77\x9a\xdd\x74\x1c\xc3\xd7\x5c\x66\x84\xc3\xda\x22\x3d\xe3\xb6\x2c\x97\x50\x48\xbb\xf5\x9e\xb5\xb4\x21\xa6\xd6\x20\x97\x6e\xd4\x6b\x6e\xd7\xaf\x89\xb2\x1e\xc4\xb2\x32\x90\x36\x7d\x52\x3b\xa6\x51\xad\x9b\xee\xaf\x7d\x35\x0c\xd5\x60\xbe\xb3\x7a\x0a\x3f\xfd\x3c\x7f\xd6\xa8\xf2\x57\x5c\x3a\x48\x58\x7c\xfb\x2d\x9b\x82\x18\xc8\x15\x12\x83\x1a\x72\x2e\x75\xad\xbc\x86\x54\xc9\x0a\xac\x96\x2d\xa7\x96\xb3\x9d\xa8\x9c\xb4\x96\xc9\xb8\x20\xba\x98\x34\x6d\x5e\x85\xce\x4b\xdd\x5c\x3b\x7e\x66\x51\x37\xb6\x0c\x58\x3a\x9d\x03\x4b\x5a\xbe\x11\x47\xb1\x32\xc5\x1c\xd8\xc5\x45\x47\x7c\xc6\x96\x30\x6e\x29\x7e\x62\x3f\x47\xe6\x3e\xb2\x52\x20\x4d\xa1\x2f\xcd\x09\x6c\xf8\xe8\x8a\xb3\x1c\xc7\xec\x12\xae\x26\xf3\x76\x36\x53\x48\xee\xda\xb7\xc6\x8f\xfe\x3f\xf7\x77\x37\x1f\x5a\xc6\x19\x7f\x60\x1b\xdf\xc3\xd1\x40\x60\xc5\xb4\x81\x5a\x71\x68\x62\xd8\xbb\xa0\x73\x88\xa3\xeb\x5b\xe5\x08\x97\xcd\x43\x83\xa9\x76\x0b\x9e\x4d\xa4\x51\xd0\xf1\x7f\xfc\xf0\xed\x37\x91\x36\x8a\x89\x15\x5b\x6e\xc7\x0f\xb5\xe2\x33\x78\x3e\x0e\xfe\xa5\x56\x3c\x98\xfc\x34\xfd\x39\x5a\x13\x5e\xe3\xa5\xf3\xf7\xcc\xfd\x3d\x92\x72\x09\xcd\xe3\x0c\x86\x02\x77\x93\xc9\xfc\x74\xbf\xab\xd7\x9e\x53\xa8\xd1\x8c\x2d\x61\x07\xfc\x43\x1b\x11\x28\xd1\x14\xd2\x85\xae\xc2\x5c\x0a\x81\xb9\x81\xba\x92\xa2\x31\x09\x70\xa9\xf5\x1e\x88\x2d\x45\x7a\x0c\x8a\x86\x3e\x75\xc9\xfa\xbf\x31\xfb\x41\xe6\x77\x68\xc6\xe3\xf1\x86\x09\x2a\x37\x11\x97\xfe\xa8\x8d\x6c\x90\xca\x5c\x72\x48\xd3\x14\x9a\x2c\x1a\x4c\xe0\x4b\x08\x36\xda\xe6\xd3\x00\x66\xf6\xd1\x3e\x4d\xe0\x02\x0e\x97\x17\x36\xdf\x5f\x40\x10\x93\x8a\x05\x13\x1f\x0e\xad\xe1\xa5\x28\x51\x6b\xb2\xc2\xbe\x82\xee\x86\xdb\x81\xcc\xee\xa3\xd4\x2b\x48\xc1\x39\xa8\x22\x4a\xa3\x27\x89\x28\x31\xa4\x45\x9b\xc5\xac\x23\x4b\x53\x10\x35\xe7\x7b\x90\xfa\xa0\x98\xb7\xf0\x1b\x90\x47\x3e\xd7\x7c\x91\xa6\x50\x0b\xea\x4c\x4c\xf7\x2b\xad\xf3\x7d\x33\x64\x12\xd9\xbc\xb0\x5f\x31\x99\xf7\xd1\x3c\xe0\x86\xf4\xb7\xd8\x21\x3d\xe4\x87\xf4\x11\x86\xae\xf7\xf4\x14\x3f\xdf\xab\xea\xb1\x73\x03\x8f\x70\x13\x75\x99\xa1\x7a\x8a\x9d\xef\x3d\x35\xec\x9c\xa9\xdf\x0a\xd3\x5b\x7b\x09\x57\xaf\x26\x8f\x70\x47\xa5\xe4\xa3\xcc\x85\x34\xdb\xf1\x03\x27\x5b\x5b\x33\xc1\xc8\xc8\xea\x8d\x6b\x15\x8d\x2e\x5d\xc6\x9d\x41\xc7\xe1\xd2\x7d\x04\x98\xc1\xc8\xbd\xd9\x79\x56\xa2\x5b\xf5\x72\x3a\x9d\x5e\x42\xfb\xf5\xec\x2f\xc4\x06\xa1\xaa\x71\xf7\x88\x3e\xba\xce\x73\x9b\xf7\x3f\x45\xa3\x86\x47\xa7\x53\xf3\xfe\x09\x5a\x75\xb9\x61\xa0\x16\xfc\xe9\x4f\x70\x34\x3b\x84\x71\x1c\xc3\x7f\x11\x75\xe7\x1a\x3b\x95\xc2\xb5\x6b\xfe\x74\xf4\x25\xd3\xda\x35\x55\x34\x50\x29\xb0\x59\xf3\x71\xc7\xfe\x91\x8e\x0d\x19\x2c\x60\x7a\xa8\xa0\x3d\x0e\x7b\x69\xe1\x44\xb6\xe8\xf1\x1d\x26\x82\xb3\x5d\x5f\xde\x60\x25\x2b\x11\xbe\x48\x21\x08\xfa\x8b\x8f\x28\x2c\x41\xc7\xec\x4c\xa3\x79\xe7\x7d\x31\x6e\xb2\xe3\xa9\xdc\x35\xb9\x84\x9b\xe9\x74\x3a\x39\x52\x62\xb7\x37\xef\xeb\xca\x96\x4d\x40\xc4\xd6\x1d\x89\x9d\x6d\x5d\xe1\x68\x4b\x20\x7b\xa4\x71\xc8\x25\xe7\xbe\x66\x69\x96\x5a\x03\x37\x4d\xb0\x14\xc2\xab\xf9\x89\x2c\xda\xb3\x64\x6f\x6b\x87\xee\x39\x61\xfb\x43\x17\x0d\x6d\x76\x40\x1c\x5e\x0d\x9c\x32\xf0\xd7\x69\xc7\x9c\x75\x7a\xb3\xbd\x45\x0f\xdc\xb5\xf7\xd7\xa1\xcd\x7a\xfa\x7b\x3e\x17\x57\x1f\xb8\x8d\x6e\xba\xaa\x75\x31\x3e\x50\x74\x32\x3f\xf6\xcd\x5b\x83\xca\x56\xc9\xd2\xa6\x2c\xeb\x0b\x7b\x15\x50\x78\xe4\x12\x57\xaa\x2b\x0c\x15\x0a\x8a\xaa\x2d\x29\x7c\x65\x6f\x0b\xc0\x81\xcb\xfc\xad\xb2\x0f\xa7\x8f\x0c\x18\x57\x92\x49\x81\x00\x00\x07\x41\xe0\x80\x3a\x40\xaa\x25\x46\x4e\x2a\x8d\x14\x52\xf0\x3f\x66\x18\x4f\xa2\x5a\xb0\xfb\xf1\x24\x6c\xde\x0f\x79\xb4\xf3\xf3\xee\x9a\xd8\xaa\x7d\x91\x42\x90\x18\x05\x8c\xa6\xa3\x00\x2e\x4e\x85\xa0\xcd\xba\xa3\xc5\x5e\x83\xfe\x52\x80\xc4\xd0\x85\xeb\x67\xfb\xfb\xda\x3f\x82\x8c\xe4\x77\x2b\x77\x11\x9a\xd9\x52\x6b\x7c\xc4\x96\xac\x89\x21\xca\x71\x9d\xcc\x61\x4f\xde\x5c\x14\x73\xeb\x9c\x39\xf8\x1b\xa9\x6b\x9b\x43\xf7\xa9\xc9\xbd\x65\x52\x51\x54\xa1\x22\x94\xd5\x7a\x06\x2f\xaa\xfb\xf9\x3f\xda\x4f\x71\xae\xb9\xff\xa4\xaa\x95\xc2\xc5\x91\x46\x4d\x93\xf8\x02\x82\x24\xb6\x04\xbf\xc5\xa6\xdb\x6c\xff\x47\x14\x70\xe2\x13\x06\x74\x3f\x71\x68\xc6\x4b\x46\x29\x47\xab\xf0\x9e\xbd\x0d\x46\xeb\xff\x7e\x48\x0d\x45\x42\xf3\xed\x62\xbf\x66\x07\xc8\x35\x3e\xb1\xa0\xfb\x0c\x32\xb2\x00\x08\xed\x96\x99\xb3\x79\x73\xd9\x76\xc3\x6a\xe4\x6c\xd1\xfc\x24\x86\xd6\xca\xd5\x5a\xe3\xb0\x01\xd8\x25\x8c\xb4\xad\xfd\xa8\x1e\x4d\xa2\xa2\x2e\x89\x60\xbf\xe2\xd8\xe6\xa5\x89\xb7\x95\xfb\xae\x12\x1c\x1f\xc9\x47\xca\xec\x3f\x78\x8c\xda\x1c\x37\x6a\x8c\x38\x6a\xbd\xfb\x62\x7f\xb7\x9f\xc1\x74\x3e\xfa\x48\x0b\x9d\x96\x12\x66\x44\x41\xff\x25\x6c\x93\x2f\x28\x69\xa5\xb7\x73\x19\x51\x23\xdf\xc9\x70\xf5\xb9\x90\x9b\x74\x74\x33\xed\x94\xf4\x8e\x76\x7e\x1e\x35\x58\x3b\x72\x86\xd5\xb2\x0d\xcd\x05\xdc\x4c\x3f\x87\xb6\xbe\x1b\x72\xb0\x03\xa3\x58\x85\x14\x48\x6e\xd8\x1a\xff\x1f\x36\xf2\x19\x8c\xfc\xd1\x2a\x5a\x1c\xb6\xc6\x73\x30\x1d\xe8\x6b\x67\x3b\xdb\xfe\xab\x8d\x37\x88\x9d\x85\x2f\x20\x38\xb9\x91\x47\x91\x78\x40\x78\x10\xda\x8f\xc7\xbd\xfb\x50\x18\x1c\xe6\x14\x5b\xed\x76\x1f\xb9\x27\x51\x61\x4a\x3e\x0e\x12\xe3\x7e\xec\x64\x75\xee\x38\x38\x06\x7e\x78\x58\xd2\xed\x86\x17\x19\x7b\x7f\xc7\x83\x7b\x16\xf4\x8a\x93\xee\x2e\xd6\x56\x22\xb0\xdb\xff\x26\x2c\x8e\xe1\x07\x43\x94\x01\x02\x3f\xbe\x85\xba\xa2\xc4\xf8\x4f\x72\x36\x3f\xfa\xae\x73\xfb\xa3\xb1\x8c\x28\x0d\x4b\xa9\x36\x44\xd1\xa6\x3f\x63\x0a\xdc\xba\x4f\x72\x6d\xe9\xa7\xd1\xbc\xb5\xa7\xd8\x9a\xf0\xf1\xd1\xbd\xef\xf9\x78\x14\xf5\x5d\x3e\x9a\x44\x48\xf2\xe2\x98\xd0\x65\xac\x4e\x6e\x0a\xdf\xb8\x2b\xc0\xf8\xf9\xd8\x14\x4c\x4f\x22\x62\x8c\x1a\x8f\x06\x60\x18\x4d\xac\x5f\xaf\x7a\x57\xb2\x6e\x79\x32\x08\xab\xa7\x78\xec\x8b\xe9\xae\x10\x68\xc9\x73\xad\xc7\x1e\x57\xa3\xcb\x1e\xef\x21\xac\x46\xe7\xa3\xce\x51\xfb\xf0\xde\xef\x23\x3d\xa9\xc9\x80\xf5\xc8\x46\xd9\xe8\x48\x3c\xa1\xf4\x8d\x8d\x9f\x71\x70\x22\xd2\x0f\xd1\x31\xe9\x8c\xed\xcf\xeb\x27\xad\xec\x7f\x5e\xf3\x88\x89\x19\x1d\x4d\x22\x5d\x67\xbe\x37\x31\x7e\xd9\x5d\xc0\x5a\x32\x07\xde\xc3\x54\x70\x54\x50\x58\x11\xc3\xa2\x22\x3c\x28\x42\x9e\xc8\x1a\x8d\x48\xbf\xab\xdd\xa5\x35\xf8\x74\xd2\xb5\xb6\xbe\xd2\xb6\xb8\xf2\xad\xff\x0d\x66\xda\x75\x12\xa0\xc1\xbb\xeb\xe6\xf8\xae\xcd\xeb\xef\xde\xf6\x3a\x37\x5d\x44\x8c\x1d\xf7\xee\xf7\x9c\xa7\xfa\x24\x27\x7f\x40\xba\xd9\x6c\x22\xff\x45\xcb\xb5\xf1\xbb\x46\x4a\x4c\x2a\x16\xbd\xd7\x01\x10\xbd\x15\x39\x50\x5c\xa2\x5a\xf4\xd8\x37\xdd\x95\x24\xf6\x3f\x6d\x4c\x62\xff\xeb\xed\xff\x0b\x00\x00\xff\xff\x56\xf8\xb5\xef\xce\x2d\x00\x00")
func faucetHtmlBytes() ([]byte, error) {
return bindataRead(
diff --git a/cmd/gmc/accountcmd.go b/cmd/gmc/accountcmd.go
index 89f53ea82..a8dc680ab 100644
--- a/cmd/gmc/accountcmd.go
+++ b/cmd/gmc/accountcmd.go
@@ -291,15 +291,28 @@ func ambiguousAddrRecovery(ks *keystore.KeyStore, err *keystore.AmbiguousAddrErr
// accountCreate creates a new account into the keystore defined by the CLI flags.
func accountCreate(ctx *cli.Context) error {
- stack, _ := makeConfigNode(ctx)
+ cfg := gmcConfig{Node: defaultNodeConfig()}
+ // Load config file.
+ if file := ctx.GlobalString(configFileFlag.Name); file != "" {
+ if err := loadConfig(file, &cfg); err != nil {
+ utils.Fatalf("%v", err)
+ }
+ }
+ utils.SetNodeConfig(ctx, &cfg.Node)
+ scryptN, scryptP, keydir, err := cfg.Node.AccountConfig()
+
+ if err != nil {
+ utils.Fatalf("Failed to read configuration: %v", err)
+ }
+
password := getPassPhrase("Your new account is locked with a password. Please give a password. Do not forget this password.", true, 0, utils.MakePasswordList(ctx))
- ks := stack.AccountManager().Backends(keystore.KeyStoreType)[0].(*keystore.KeyStore)
- account, err := ks.NewAccount(password)
+ address, err := keystore.StoreKey(keydir, password, scryptN, scryptP)
+
if err != nil {
utils.Fatalf("Failed to create account: %v", err)
}
- fmt.Printf("Address: {%x}\n", account.Address)
+ fmt.Printf("Address: {%x}\n", address)
return nil
}
diff --git a/cmd/puppeth/genesis.go b/cmd/puppeth/genesis.go
new file mode 100644
index 000000000..10ef6d237
--- /dev/null
+++ b/cmd/puppeth/genesis.go
@@ -0,0 +1,381 @@
+// Copyright 2017 The go-ethereum Authors
+// This file is part of go-ethereum.
+//
+// go-ethereum is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// go-ethereum is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with go-ethereum. If not, see .
+
+package main
+
+import (
+ "encoding/binary"
+ "errors"
+ "math"
+
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/common/hexutil"
+ "github.com/ethereum/go-ethereum/consensus/ethash"
+ "github.com/ethereum/go-ethereum/core"
+ "github.com/ethereum/go-ethereum/params"
+)
+
+// cppEthereumGenesisSpec represents the genesis specification format used by the
+// C++ Ethereum implementation.
+type cppEthereumGenesisSpec struct {
+ SealEngine string `json:"sealEngine"`
+ Params struct {
+ AccountStartNonce hexutil.Uint64 `json:"accountStartNonce"`
+ HomesteadForkBlock hexutil.Uint64 `json:"homesteadForkBlock"`
+ EIP150ForkBlock hexutil.Uint64 `json:"EIP150ForkBlock"`
+ EIP158ForkBlock hexutil.Uint64 `json:"EIP158ForkBlock"`
+ UBIForkBlock hexutil.Uint64 `json:"UBIForkBlock"`
+ ByzantiumForkBlock hexutil.Uint64 `json:"byzantiumForkBlock"`
+ ConstantinopleForkBlock hexutil.Uint64 `json:"constantinopleForkBlock"`
+ NetworkID hexutil.Uint64 `json:"networkID"`
+ ChainID hexutil.Uint64 `json:"chainID"`
+ MaximumExtraDataSize hexutil.Uint64 `json:"maximumExtraDataSize"`
+ MinGasLimit hexutil.Uint64 `json:"minGasLimit"`
+ MaxGasLimit hexutil.Uint64 `json:"maxGasLimit"`
+ GasLimitBoundDivisor *hexutil.Big `json:"gasLimitBoundDivisor"`
+ MinimumDifficulty *hexutil.Big `json:"minimumDifficulty"`
+ DifficultyBoundDivisor *hexutil.Big `json:"difficultyBoundDivisor"`
+ DurationLimit *hexutil.Big `json:"durationLimit"`
+ BlockReward *hexutil.Big `json:"blockReward"`
+ } `json:"params"`
+
+ Genesis struct {
+ Nonce hexutil.Bytes `json:"nonce"`
+ Difficulty *hexutil.Big `json:"difficulty"`
+ MixHash common.Hash `json:"mixHash"`
+ Author common.Address `json:"author"`
+ Timestamp hexutil.Uint64 `json:"timestamp"`
+ ParentHash common.Hash `json:"parentHash"`
+ ExtraData hexutil.Bytes `json:"extraData"`
+ GasLimit hexutil.Uint64 `json:"gasLimit"`
+ } `json:"genesis"`
+
+ Accounts map[common.Address]*cppEthereumGenesisSpecAccount `json:"accounts"`
+}
+
+// cppEthereumGenesisSpecAccount is the prefunded genesis account and/or precompiled
+// contract definition.
+type cppEthereumGenesisSpecAccount struct {
+ Balance *hexutil.Big `json:"balance"`
+ Nonce uint64 `json:"nonce,omitempty"`
+ Precompiled *cppEthereumGenesisSpecBuiltin `json:"precompiled,omitempty"`
+}
+
+// cppEthereumGenesisSpecBuiltin is the precompiled contract definition.
+type cppEthereumGenesisSpecBuiltin struct {
+ Name string `json:"name,omitempty"`
+ StartingBlock hexutil.Uint64 `json:"startingBlock,omitempty"`
+ Linear *cppEthereumGenesisSpecLinearPricing `json:"linear,omitempty"`
+}
+
+type cppEthereumGenesisSpecLinearPricing struct {
+ Base uint64 `json:"base"`
+ Word uint64 `json:"word"`
+}
+
+// newCppEthereumGenesisSpec converts a go-ethereum genesis block into a Parity specific
+// chain specification format.
+func newCppEthereumGenesisSpec(network string, genesis *core.Genesis) (*cppEthereumGenesisSpec, error) {
+ // Only ethash is currently supported between go-ethereum and cpp-ethereum
+ if genesis.Config.Ethash == nil {
+ return nil, errors.New("unsupported consensus engine")
+ }
+ // Reconstruct the chain spec in Parity's format
+ spec := &cppEthereumGenesisSpec{
+ SealEngine: "Ethash",
+ }
+ spec.Params.AccountStartNonce = 0
+ spec.Params.HomesteadForkBlock = (hexutil.Uint64)(genesis.Config.HomesteadBlock.Uint64())
+ spec.Params.EIP150ForkBlock = (hexutil.Uint64)(genesis.Config.EIP150Block.Uint64())
+ spec.Params.EIP158ForkBlock = (hexutil.Uint64)(genesis.Config.EIP158Block.Uint64())
+ spec.Params.UBIForkBlock = (hexutil.Uint64)(genesis.Config.UBIForkBlock.Uint64())
+ spec.Params.ByzantiumForkBlock = (hexutil.Uint64)(genesis.Config.ByzantiumBlock.Uint64())
+ spec.Params.ConstantinopleForkBlock = (hexutil.Uint64)(math.MaxUint64)
+
+ spec.Params.NetworkID = (hexutil.Uint64)(genesis.Config.ChainId.Uint64())
+ spec.Params.ChainID = (hexutil.Uint64)(genesis.Config.ChainId.Uint64())
+
+ spec.Params.MaximumExtraDataSize = (hexutil.Uint64)(params.MaximumExtraDataSize)
+ spec.Params.MinGasLimit = (hexutil.Uint64)(params.MinGasLimit.Uint64())
+ spec.Params.MaxGasLimit = (hexutil.Uint64)(math.MaxUint64)
+ spec.Params.MinimumDifficulty = (*hexutil.Big)(params.MinimumDifficulty)
+ spec.Params.DifficultyBoundDivisor = (*hexutil.Big)(params.DifficultyBoundDivisor)
+ spec.Params.GasLimitBoundDivisor = (*hexutil.Big)(params.GasLimitBoundDivisor)
+ spec.Params.DurationLimit = (*hexutil.Big)(params.DurationLimit)
+ spec.Params.BlockReward = (*hexutil.Big)(ethash.FrontierBlockReward)
+
+ spec.Genesis.Nonce = (hexutil.Bytes)(make([]byte, 8))
+ binary.LittleEndian.PutUint64(spec.Genesis.Nonce[:], genesis.Nonce)
+
+ spec.Genesis.MixHash = genesis.Mixhash
+ spec.Genesis.Difficulty = (*hexutil.Big)(genesis.Difficulty)
+ spec.Genesis.Author = genesis.Coinbase
+ spec.Genesis.Timestamp = (hexutil.Uint64)(genesis.Timestamp)
+ spec.Genesis.ParentHash = genesis.ParentHash
+ spec.Genesis.ExtraData = (hexutil.Bytes)(genesis.ExtraData)
+ spec.Genesis.GasLimit = (hexutil.Uint64)(genesis.GasLimit)
+
+ spec.Accounts = make(map[common.Address]*cppEthereumGenesisSpecAccount)
+ for address, account := range genesis.Alloc {
+ spec.Accounts[address] = &cppEthereumGenesisSpecAccount{
+ Balance: (*hexutil.Big)(account.Balance),
+ Nonce: account.Nonce,
+ }
+ }
+ spec.Accounts[common.BytesToAddress([]byte{1})].Precompiled = &cppEthereumGenesisSpecBuiltin{
+ Name: "ecrecover", Linear: &cppEthereumGenesisSpecLinearPricing{Base: 3000},
+ }
+ spec.Accounts[common.BytesToAddress([]byte{2})].Precompiled = &cppEthereumGenesisSpecBuiltin{
+ Name: "sha256", Linear: &cppEthereumGenesisSpecLinearPricing{Base: 60, Word: 12},
+ }
+ spec.Accounts[common.BytesToAddress([]byte{3})].Precompiled = &cppEthereumGenesisSpecBuiltin{
+ Name: "ripemd160", Linear: &cppEthereumGenesisSpecLinearPricing{Base: 600, Word: 120},
+ }
+ spec.Accounts[common.BytesToAddress([]byte{4})].Precompiled = &cppEthereumGenesisSpecBuiltin{
+ Name: "identity", Linear: &cppEthereumGenesisSpecLinearPricing{Base: 15, Word: 3},
+ }
+ if genesis.Config.ByzantiumBlock != nil {
+ spec.Accounts[common.BytesToAddress([]byte{5})].Precompiled = &cppEthereumGenesisSpecBuiltin{
+ Name: "modexp", StartingBlock: (hexutil.Uint64)(genesis.Config.ByzantiumBlock.Uint64()),
+ }
+ spec.Accounts[common.BytesToAddress([]byte{6})].Precompiled = &cppEthereumGenesisSpecBuiltin{
+ Name: "alt_bn128_G1_add", StartingBlock: (hexutil.Uint64)(genesis.Config.ByzantiumBlock.Uint64()), Linear: &cppEthereumGenesisSpecLinearPricing{Base: 500},
+ }
+ spec.Accounts[common.BytesToAddress([]byte{7})].Precompiled = &cppEthereumGenesisSpecBuiltin{
+ Name: "alt_bn128_G1_mul", StartingBlock: (hexutil.Uint64)(genesis.Config.ByzantiumBlock.Uint64()), Linear: &cppEthereumGenesisSpecLinearPricing{Base: 40000},
+ }
+ spec.Accounts[common.BytesToAddress([]byte{8})].Precompiled = &cppEthereumGenesisSpecBuiltin{
+ Name: "alt_bn128_pairing_product", StartingBlock: (hexutil.Uint64)(genesis.Config.ByzantiumBlock.Uint64()),
+ }
+ }
+ return spec, nil
+}
+
+// parityChainSpec is the chain specification format used by Parity.
+type parityChainSpec struct {
+ Name string `json:"name"`
+ Engine struct {
+ Ethash struct {
+ Params struct {
+ MinimumDifficulty *hexutil.Big `json:"minimumDifficulty"`
+ DifficultyBoundDivisor *hexutil.Big `json:"difficultyBoundDivisor"`
+ GasLimitBoundDivisor *hexutil.Big `json:"gasLimitBoundDivisor"`
+ DurationLimit *hexutil.Big `json:"durationLimit"`
+ BlockReward *hexutil.Big `json:"blockReward"`
+ HomesteadTransition uint64 `json:"homesteadTransition"`
+ EIP150Transition uint64 `json:"eip150Transition"`
+ EIP160Transition uint64 `json:"eip160Transition"`
+ EIP161abcTransition uint64 `json:"eip161abcTransition"`
+ EIP161dTransition uint64 `json:"eip161dTransition"`
+ EIP649Reward *hexutil.Big `json:"eip649Reward"`
+ EIP100bTransition uint64 `json:"eip100bTransition"`
+ EIP649Transition uint64 `json:"eip649Transition"`
+ } `json:"params"`
+ } `json:"Ethash"`
+ } `json:"engine"`
+
+ Params struct {
+ MaximumExtraDataSize hexutil.Uint64 `json:"maximumExtraDataSize"`
+ MinGasLimit *hexutil.Big `json:"minGasLimit"`
+ NetworkID hexutil.Uint64 `json:"networkID"`
+ MaxCodeSize uint64 `json:"maxCodeSize"`
+ EIP155Transition uint64 `json:"eip155Transition"`
+ EIP98Transition uint64 `json:"eip98Transition"`
+ EIP86Transition uint64 `json:"eip86Transition"`
+ EIP140Transition uint64 `json:"eip140Transition"`
+ EIP211Transition uint64 `json:"eip211Transition"`
+ EIP214Transition uint64 `json:"eip214Transition"`
+ EIP658Transition uint64 `json:"eip658Transition"`
+ } `json:"params"`
+
+ Genesis struct {
+ Seal struct {
+ Ethereum struct {
+ Nonce hexutil.Bytes `json:"nonce"`
+ MixHash hexutil.Bytes `json:"mixHash"`
+ } `json:"ethereum"`
+ } `json:"seal"`
+
+ Difficulty *hexutil.Big `json:"difficulty"`
+ Author common.Address `json:"author"`
+ Timestamp hexutil.Uint64 `json:"timestamp"`
+ ParentHash common.Hash `json:"parentHash"`
+ ExtraData hexutil.Bytes `json:"extraData"`
+ GasLimit hexutil.Uint64 `json:"gasLimit"`
+ } `json:"genesis"`
+
+ Nodes []string `json:"nodes"`
+ Accounts map[common.Address]*parityChainSpecAccount `json:"accounts"`
+}
+
+// parityChainSpecAccount is the prefunded genesis account and/or precompiled
+// contract definition.
+type parityChainSpecAccount struct {
+ Balance *hexutil.Big `json:"balance"`
+ Nonce uint64 `json:"nonce,omitempty"`
+ Builtin *parityChainSpecBuiltin `json:"builtin,omitempty"`
+}
+
+// parityChainSpecBuiltin is the precompiled contract definition.
+type parityChainSpecBuiltin struct {
+ Name string `json:"name,omitempty"`
+ ActivateAt uint64 `json:"activate_at,omitempty"`
+ Pricing *parityChainSpecPricing `json:"pricing,omitempty"`
+}
+
+// parityChainSpecPricing represents the different pricing models that builtin
+// contracts might advertise using.
+type parityChainSpecPricing struct {
+ Linear *parityChainSpecLinearPricing `json:"linear,omitempty"`
+ ModExp *parityChainSpecModExpPricing `json:"modexp,omitempty"`
+ AltBnPairing *parityChainSpecAltBnPairingPricing `json:"alt_bn128_pairing,omitempty"`
+}
+
+type parityChainSpecLinearPricing struct {
+ Base uint64 `json:"base"`
+ Word uint64 `json:"word"`
+}
+
+type parityChainSpecModExpPricing struct {
+ Divisor uint64 `json:"divisor"`
+}
+
+type parityChainSpecAltBnPairingPricing struct {
+ Base uint64 `json:"base"`
+ Pair uint64 `json:"pair"`
+}
+
+// newParityChainSpec converts a go-ethereum genesis block into a Parity specific
+// chain specification format.
+func newParityChainSpec(network string, genesis *core.Genesis, bootnodes []string) (*parityChainSpec, error) {
+ // Only ethash is currently supported between go-ethereum and Parity
+ if genesis.Config.Ethash == nil {
+ return nil, errors.New("unsupported consensus engine")
+ }
+ // Reconstruct the chain spec in Parity's format
+ spec := &parityChainSpec{
+ Name: network,
+ Nodes: bootnodes,
+ }
+ spec.Engine.Ethash.Params.MinimumDifficulty = (*hexutil.Big)(params.MinimumDifficulty)
+ spec.Engine.Ethash.Params.DifficultyBoundDivisor = (*hexutil.Big)(params.DifficultyBoundDivisor)
+ spec.Engine.Ethash.Params.GasLimitBoundDivisor = (*hexutil.Big)(params.GasLimitBoundDivisor)
+ spec.Engine.Ethash.Params.DurationLimit = (*hexutil.Big)(params.DurationLimit)
+ spec.Engine.Ethash.Params.BlockReward = (*hexutil.Big)(ethash.FrontierBlockReward)
+ spec.Engine.Ethash.Params.HomesteadTransition = genesis.Config.HomesteadBlock.Uint64()
+ spec.Engine.Ethash.Params.EIP150Transition = genesis.Config.EIP150Block.Uint64()
+ spec.Engine.Ethash.Params.EIP160Transition = genesis.Config.EIP155Block.Uint64()
+ spec.Engine.Ethash.Params.EIP161abcTransition = genesis.Config.EIP158Block.Uint64()
+ spec.Engine.Ethash.Params.EIP161dTransition = genesis.Config.EIP158Block.Uint64()
+ spec.Engine.Ethash.Params.EIP649Reward = (*hexutil.Big)(ethash.ByzantiumBlockReward)
+ spec.Engine.Ethash.Params.EIP100bTransition = genesis.Config.ByzantiumBlock.Uint64()
+ spec.Engine.Ethash.Params.EIP649Transition = genesis.Config.ByzantiumBlock.Uint64()
+
+ spec.Params.MaximumExtraDataSize = (hexutil.Uint64)(params.MaximumExtraDataSize)
+ spec.Params.MinGasLimit = (*hexutil.Big)(params.MinGasLimit)
+ spec.Params.NetworkID = (hexutil.Uint64)(genesis.Config.ChainId.Uint64())
+ spec.Params.MaxCodeSize = params.MaxCodeSize
+ spec.Params.EIP155Transition = genesis.Config.EIP155Block.Uint64()
+ spec.Params.EIP98Transition = math.MaxUint64
+ spec.Params.EIP86Transition = math.MaxUint64
+ spec.Params.EIP140Transition = genesis.Config.ByzantiumBlock.Uint64()
+ spec.Params.EIP211Transition = genesis.Config.ByzantiumBlock.Uint64()
+ spec.Params.EIP214Transition = genesis.Config.ByzantiumBlock.Uint64()
+ spec.Params.EIP658Transition = genesis.Config.ByzantiumBlock.Uint64()
+
+ spec.Genesis.Seal.Ethereum.Nonce = (hexutil.Bytes)(make([]byte, 8))
+ binary.LittleEndian.PutUint64(spec.Genesis.Seal.Ethereum.Nonce[:], genesis.Nonce)
+
+ spec.Genesis.Seal.Ethereum.MixHash = (hexutil.Bytes)(genesis.Mixhash[:])
+ spec.Genesis.Difficulty = (*hexutil.Big)(genesis.Difficulty)
+ spec.Genesis.Author = genesis.Coinbase
+ spec.Genesis.Timestamp = (hexutil.Uint64)(genesis.Timestamp)
+ spec.Genesis.ParentHash = genesis.ParentHash
+ spec.Genesis.ExtraData = (hexutil.Bytes)(genesis.ExtraData)
+ spec.Genesis.GasLimit = (hexutil.Uint64)(genesis.GasLimit)
+
+ spec.Accounts = make(map[common.Address]*parityChainSpecAccount)
+ for address, account := range genesis.Alloc {
+ spec.Accounts[address] = &parityChainSpecAccount{
+ Balance: (*hexutil.Big)(account.Balance),
+ Nonce: account.Nonce,
+ }
+ }
+ spec.Accounts[common.BytesToAddress([]byte{1})].Builtin = &parityChainSpecBuiltin{
+ Name: "ecrecover", Pricing: &parityChainSpecPricing{Linear: &parityChainSpecLinearPricing{Base: 3000}},
+ }
+ spec.Accounts[common.BytesToAddress([]byte{2})].Builtin = &parityChainSpecBuiltin{
+ Name: "sha256", Pricing: &parityChainSpecPricing{Linear: &parityChainSpecLinearPricing{Base: 60, Word: 12}},
+ }
+ spec.Accounts[common.BytesToAddress([]byte{3})].Builtin = &parityChainSpecBuiltin{
+ Name: "ripemd160", Pricing: &parityChainSpecPricing{Linear: &parityChainSpecLinearPricing{Base: 600, Word: 120}},
+ }
+ spec.Accounts[common.BytesToAddress([]byte{4})].Builtin = &parityChainSpecBuiltin{
+ Name: "identity", Pricing: &parityChainSpecPricing{Linear: &parityChainSpecLinearPricing{Base: 15, Word: 3}},
+ }
+ if genesis.Config.ByzantiumBlock != nil {
+ spec.Accounts[common.BytesToAddress([]byte{5})].Builtin = &parityChainSpecBuiltin{
+ Name: "modexp", ActivateAt: genesis.Config.ByzantiumBlock.Uint64(), Pricing: &parityChainSpecPricing{ModExp: &parityChainSpecModExpPricing{Divisor: 20}},
+ }
+ spec.Accounts[common.BytesToAddress([]byte{6})].Builtin = &parityChainSpecBuiltin{
+ Name: "alt_bn128_add", ActivateAt: genesis.Config.ByzantiumBlock.Uint64(), Pricing: &parityChainSpecPricing{Linear: &parityChainSpecLinearPricing{Base: 500}},
+ }
+ spec.Accounts[common.BytesToAddress([]byte{7})].Builtin = &parityChainSpecBuiltin{
+ Name: "alt_bn128_mul", ActivateAt: genesis.Config.ByzantiumBlock.Uint64(), Pricing: &parityChainSpecPricing{Linear: &parityChainSpecLinearPricing{Base: 40000}},
+ }
+ spec.Accounts[common.BytesToAddress([]byte{8})].Builtin = &parityChainSpecBuiltin{
+ Name: "alt_bn128_pairing", ActivateAt: genesis.Config.ByzantiumBlock.Uint64(), Pricing: &parityChainSpecPricing{AltBnPairing: &parityChainSpecAltBnPairingPricing{Base: 100000, Pair: 80000}},
+ }
+ }
+ return spec, nil
+}
+
+// pyEthereumGenesisSpec represents the genesis specification format used by the
+// Python Ethereum implementation.
+type pyEthereumGenesisSpec struct {
+ Nonce hexutil.Bytes `json:"nonce"`
+ Timestamp hexutil.Uint64 `json:"timestamp"`
+ ExtraData hexutil.Bytes `json:"extraData"`
+ GasLimit hexutil.Uint64 `json:"gasLimit"`
+ Difficulty *hexutil.Big `json:"difficulty"`
+ Mixhash common.Hash `json:"mixhash"`
+ Coinbase common.Address `json:"coinbase"`
+ Alloc core.GenesisAlloc `json:"alloc"`
+ ParentHash common.Hash `json:"parentHash"`
+}
+
+// newPyEthereumGenesisSpec converts a go-ethereum genesis block into a Parity specific
+// chain specification format.
+func newPyEthereumGenesisSpec(network string, genesis *core.Genesis) (*pyEthereumGenesisSpec, error) {
+ // Only ethash is currently supported between go-ethereum and pyethereum
+ if genesis.Config.Ethash == nil {
+ return nil, errors.New("unsupported consensus engine")
+ }
+ spec := &pyEthereumGenesisSpec{
+ Timestamp: (hexutil.Uint64)(genesis.Timestamp),
+ ExtraData: genesis.ExtraData,
+ GasLimit: (hexutil.Uint64)(genesis.GasLimit),
+ Difficulty: (*hexutil.Big)(genesis.Difficulty),
+ Mixhash: genesis.Mixhash,
+ Coinbase: genesis.Coinbase,
+ Alloc: genesis.Alloc,
+ ParentHash: genesis.ParentHash,
+ }
+ spec.Nonce = (hexutil.Bytes)(make([]byte, 8))
+ binary.LittleEndian.PutUint64(spec.Nonce[:], genesis.Nonce)
+
+ return spec, nil
+}
diff --git a/cmd/puppeth/module_dashboard.go b/cmd/puppeth/module_dashboard.go
index ae6075447..f01e31a48 100644
--- a/cmd/puppeth/module_dashboard.go
+++ b/cmd/puppeth/module_dashboard.go
@@ -18,10 +18,12 @@ package main
import (
"bytes"
+ "encoding/json"
"fmt"
"html/template"
"math/rand"
"path/filepath"
+ "strconv"
"strings"
"github.com/ethereum/go-ethereum/log"
@@ -76,25 +78,26 @@ var dashboardContent = `
A full node synchronizes the blockchain by downloading the full chain from the genesis block to the current head block, but does not execute the transactions. Instead, it downloads all the transactions receipts along with the entire recent state. As the node downloads the recent state directly, historical data can only be queried from that block onward.
Initial processing required to synchronize is more bandwidth intensive, but is light on the CPU and has significantly reduced disk requirements. Mid range machines with HDD storage, decent CPUs and 4GB+ RAM should be enough.
-
To run a full node, download {{.GMCGenesis}} and start GCM with:
+
To run a full node, download {{.GMCGenesis}} and start GMC with:
Initial processing required to synchronize is light, as it only verifies the validity of the headers; similarly required disk capacity is small, tallying around 500 bytes per header. Low end machines with arbitrary storage, weak CPUs and 512MB+ RAM should cope well.
To run a light node, download {{.GMCGenesis}} and start GMC with:
-
Initial processing required to synchronize is light, as it only verifies the validity of the headers; similarly required disk capacity is small, tallying around 500 bytes per header. Embedded machines with arbitrary storage, low power CPUs and 128MB+ RAM may work.
To run an embedded node, download {{.GMCGenesis}} and start GMC with:
-
The Ethereum Wallet is an Electron based desktop application to manage your Ethereum accounts and funds. Beside the usual account life-cycle operations you would expect to perform, the wallet also provides a means to send transactions from your accounts and to interact with smart contracts deployed on the network.
-
Under the hood the wallet is backed by a go-ethereum full node, meaning that a mid range machine is assumed. Similarly, synchronization is based on fast-sync, which will download all blockchain data from the network and make it available to the wallet. Light nodes cannot currently fully back the wallet, but it's a target actively pursued.
+
The Musicoin Wallet is an Electron based desktop application to manage your Musicoin accounts and funds. Beside the usual account life-cycle operations you would expect to perform, the wallet also provides a means to send transactions from your accounts and to interact with smart contracts deployed on the network.
+
Under the hood the wallet is backed by a go-musicoin full node, meaning that a mid range machine is assumed. Similarly, synchronization is based on fast-sync, which will download all blockchain data from the network and make it available to the wallet. Light nodes cannot currently fully back the wallet, but it's a target actively pursued.
-
To connect with the Ethereum Wallet, you'll need to initialize your private network first via GMC as the wallet does not currently support calling GMC directly. To initialize your local chain, download {{.GMCGenesis}} and run:
+
To connect with the Musicoin Wallet, you'll need to initialize your private network first via GMC as the wallet does not currently support calling GMC directly. To initialize your local chain, download {{.GMCGenesis}} and run:
The Mist browser is an Electron based desktop application to load and interact with Ethereum enabled third party web DApps. Beside all the functionality provided by the Ethereum Wallet, Mist is an extended web-browser where loaded pages have access to the Ethereum network via a web3.js provider, and may also interact with users' own accounts (given proper authorization and confirmation of course).
-
Under the hood the browser is backed by a go-ethereum full node, meaning that a mid range machine is assumed. Similarly, synchronization is based on fast-sync, which will download all blockchain data from the network and make it available to the wallet. Light nodes cannot currently fully back the wallet, but it's a target actively pursued.
+
The Mist browser is an Electron based desktop application to load and interact with Musicoin enabled third party web DApps. Beside all the functionality provided by the Musicoin Wallet, Mist is an extended web-browser where loaded pages have access to the Musicoin network via a web3.js provider, and may also interact with users' own accounts (given proper authorization and confirmation of course).
+
Under the hood the browser is backed by a go-musicoin full node, meaning that a mid range machine is assumed. Similarly, synchronization is based on fast-sync, which will download all blockchain data from the network and make it available to the wallet. Light nodes cannot currently fully back the wallet, but it's a target actively pursued.
To connect with the Mist browser, you'll need to initialize your private network first via GMC as Mist does not currently support calling GMC directly. To initialize your local chain, download {{.GMCGenesis}} and run:
The stable Android archives are distributed via Maven Central, and the develop snapshots via the Sonatype repositories. Before proceeding, please ensure you have a recent version configured in your Android project. You can find details in Mobile: Introduction – Android archive.
Before connecting to the Musicoin network, download the {{.GMCGenesis}} genesis json file and either store it in your Android project as a resource file you can access, or save it as a string in a variable. You're going to need to to initialize your client.
-
Inside your Java code you can now import the gmc archive and connect to Musicoin:
+
Inside your Java code you can now import the GMC archive and connect to Musicoin:
+
+ C++ Ethereum Official C++ client from the Ethereum Foundation
+
+
+
+
+
C++ Ethereum is the third most popular of the Ethereum clients, focusing on code portability to a broad range of operating systems and hardware. The client is currently a full node with transaction processing based synchronization.
+
+
To run a cpp-ethereum node, download {{.CppGenesis}} and start the node with:
+
eth --config {{.CppGenesis}} --datadir $HOME/.{{.Network}} --peerset "{{.CppBootnodes}}"
+
+ Ethereum HarmonyThird party Java client from EtherCamp
+
+
+
+
+
Ethereum Harmony is a web user-interface based graphical Ethereum client built on top of the EthereumJ Java implementation of the Ethereum protocol. The client currently is a full node with state download based synchronization.
+
+
To run an Ethereum Harmony node, download {{.HarmonyGenesis}} and start the node with:
+
+
+ ParityThird party Rust client from Parity Technologies
+
+
+
+
+
Parity is a fast, light and secure Musicoin client, supporting both headless mode of operation as well as a web user interface for direct manual interaction. The client is currently a full node with transaction processing based synchronization and state pruning enabled.
+
+
To run a Parity node, download {{.ParityGenesis}} and start the node with:
+
+
+ PyEthAppOfficial Python client from the Ethereum Foundation
+
+
+
+
+
Pyethapp is the Ethereum Foundation's research client, aiming to provide an easily hackable and extendable codebase. The client is currently a full node with transaction processing based synchronization and state pruning enabled.
+
+
To run a pyethapp node, download {{.PythonGenesis}} and start the node with:
+
Puppeth is a tool to aid you in creating a new Ethereum network down to the genesis block, bootnodes, signers, ethstats server, crypto faucet, wallet browsers, block explorer, dashboard and more; without the hassle that it would normally entail to manually configure all these services one by one.
Puppeth uses ssh to dial in to remote servers, and builds its network components out of docker containers using docker-compose. The user is guided through the process via a command line wizard that does the heavy lifting and topology configuration automatically behind the scenes.
-
Puppeth is distributed as part of the GMC & Tools bundles, but can also be installed separately via:
go get github.com/ethereum/go-ethereum/cmd/puppeth
+
Puppeth is distributed as part of the GMC & Tools bundles, but can also be installed separately via:
go get github.com/ethereum/go-ethereum/cmd/puppeth