mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-23 05:06:43 +00:00
Merge branch 'bzz' of https://github.com/ethersphere/go-ethereum into bzz
Conflicts: bzz/api.go
This commit is contained in:
commit
600e6fa584
11 changed files with 384 additions and 128 deletions
79
bzz/api.go
79
bzz/api.go
|
|
@ -62,6 +62,30 @@ func NewApi(datadir, port string) (self *Api, err error) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Local swarm without netStore
|
||||||
|
func NewLocalApi(datadir string) (self *Api, err error) {
|
||||||
|
|
||||||
|
self = &Api{
|
||||||
|
Chunker: &TreeChunker{},
|
||||||
|
}
|
||||||
|
dbStore, err := newDbStore(datadir)
|
||||||
|
dbStore.setCapacity(50000)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
memStore := newMemStore(dbStore)
|
||||||
|
localStore := &localStore{
|
||||||
|
memStore,
|
||||||
|
dbStore,
|
||||||
|
}
|
||||||
|
|
||||||
|
self.dpa = &DPA{
|
||||||
|
Chunker: self.Chunker,
|
||||||
|
ChunkStore: localStore,
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// Bzz returns the bzz protocol class instances of which run on every peer
|
// Bzz returns the bzz protocol class instances of which run on every peer
|
||||||
func (self *Api) Bzz() (p2p.Protocol, error) {
|
func (self *Api) Bzz() (p2p.Protocol, error) {
|
||||||
return BzzProtocol(self.netStore)
|
return BzzProtocol(self.netStore)
|
||||||
|
|
@ -77,9 +101,15 @@ Start is called when the ethereum stack is started
|
||||||
func (self *Api) Start(node *discover.Node, connectPeer func(string) error) {
|
func (self *Api) Start(node *discover.Node, connectPeer func(string) error) {
|
||||||
self.Chunker.Init()
|
self.Chunker.Init()
|
||||||
self.dpa.Start()
|
self.dpa.Start()
|
||||||
self.netStore.start(node, connectPeer)
|
if node != nil && self.netStore != nil && connectPeer != nil {
|
||||||
dpaLogger.Infof("Swarm started.")
|
self.netStore.start(node, connectPeer)
|
||||||
go startHttpServer(self, self.Port)
|
dpaLogger.Infof("Swarm network started.")
|
||||||
|
} else {
|
||||||
|
dpaLogger.Infof("Local Swarm started without network")
|
||||||
|
}
|
||||||
|
if self.Port != "" {
|
||||||
|
go startHttpServer(self, self.Port)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *Api) Stop() {
|
func (self *Api) Stop() {
|
||||||
|
|
@ -158,7 +188,7 @@ const maxParallelFiles = 5
|
||||||
// Upload replicates a local directory as a manifest file and uploads it
|
// Upload replicates a local directory as a manifest file and uploads it
|
||||||
// using dpa store
|
// using dpa store
|
||||||
// TODO: localpath should point to a manifest
|
// TODO: localpath should point to a manifest
|
||||||
func (self *Api) Upload(lpath string) (string, error) {
|
func (self *Api) Upload(lpath, index string) (string, error) {
|
||||||
var list []*manifestTrieEntry
|
var list []*manifestTrieEntry
|
||||||
localpath, err := filepath.Abs(filepath.Clean(lpath))
|
localpath, err := filepath.Abs(filepath.Clean(lpath))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -263,6 +293,15 @@ func (self *Api) Upload(lpath string) (string, error) {
|
||||||
}
|
}
|
||||||
entry.Path = regularSlashes(entry.Path[start:])
|
entry.Path = regularSlashes(entry.Path[start:])
|
||||||
trie.addEntry(entry)
|
trie.addEntry(entry)
|
||||||
|
|
||||||
|
if entry.Path == index {
|
||||||
|
ientry := &manifestTrieEntry{
|
||||||
|
Path: "",
|
||||||
|
Hash: entry.Hash,
|
||||||
|
ContentType: entry.ContentType,
|
||||||
|
}
|
||||||
|
trie.addEntry(ientry)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
err2 := trie.recalcAndStore()
|
err2 := trie.recalcAndStore()
|
||||||
|
|
@ -277,6 +316,7 @@ func (self *Api) Register(sender common.Address, hash common.Hash, domain string
|
||||||
domainhash := common.BytesToHash(crypto.Sha3([]byte(domain)))
|
domainhash := common.BytesToHash(crypto.Sha3([]byte(domain)))
|
||||||
|
|
||||||
if self.Resolver != nil {
|
if self.Resolver != nil {
|
||||||
|
dpaLogger.Debugf("Swarm: host '%s' (hash: '%v') to be registered as '%v'", domain, domainhash.Hex(), hash.Hex())
|
||||||
_, err = self.Resolver.RegisterContentHash(sender, domainhash, hash)
|
_, err = self.Resolver.RegisterContentHash(sender, domainhash, hash)
|
||||||
} else {
|
} else {
|
||||||
err = fmt.Errorf("no registry: %v", err)
|
err = fmt.Errorf("no registry: %v", err)
|
||||||
|
|
@ -286,15 +326,16 @@ func (self *Api) Register(sender common.Address, hash common.Hash, domain string
|
||||||
|
|
||||||
type errResolve error
|
type errResolve error
|
||||||
|
|
||||||
func (self *Api) Resolve(hostport string) (contentHash Key, errR errResolve) {
|
func (self *Api) Resolve(hostPort string) (contentHash Key, err error) {
|
||||||
var host, port string
|
var host string
|
||||||
var err error
|
host, _, err = net.SplitHostPort(hostPort)
|
||||||
host, port, err = net.SplitHostPort(hostport)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if err.Error() == "missing port in address "+hostport {
|
porterr := "missing port in address " + hostPort
|
||||||
host = hostport
|
if err.Error() == porterr {
|
||||||
|
host = hostPort
|
||||||
|
err = nil
|
||||||
} else {
|
} else {
|
||||||
errR = errResolve(fmt.Errorf("invalid host '%s': %v", hostport, err))
|
err = fmt.Errorf("invalid host '%s': %v (<>'%s')", hostPort, err, porterr)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -303,18 +344,16 @@ func (self *Api) Resolve(hostport string) (contentHash Key, errR errResolve) {
|
||||||
dpaLogger.Debugf("Swarm: host is a contentHash: '%064x'", contentHash)
|
dpaLogger.Debugf("Swarm: host is a contentHash: '%064x'", contentHash)
|
||||||
} else {
|
} else {
|
||||||
if self.Resolver != nil {
|
if self.Resolver != nil {
|
||||||
hostHash := common.BytesToHash(crypto.Sha3(common.Hex2Bytes(host)))
|
hostHash := common.BytesToHash(crypto.Sha3([]byte(host)))
|
||||||
// TODO: should take port as block number versioning
|
|
||||||
_ = port
|
|
||||||
var hash common.Hash
|
var hash common.Hash
|
||||||
hash, err = self.Resolver.KeyToContentHash(hostHash)
|
hash, err = self.Resolver.KeyToContentHash(hostHash)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
err = errResolve(fmt.Errorf("unable to resolve '%s': %v", hostport, err))
|
err = fmt.Errorf("unable to resolve '%s': %v", hostPort, err)
|
||||||
}
|
}
|
||||||
contentHash = Key(hash.Bytes())
|
contentHash = Key(hash.Bytes())
|
||||||
dpaLogger.Debugf("Swarm: resolve host to contentHash: '%064x'", contentHash)
|
dpaLogger.Debugf("Swarm: resolve host '%s' to contentHash: '%064x'", hostPort, contentHash)
|
||||||
} else {
|
} else {
|
||||||
err = errResolve(fmt.Errorf("no resolver '%s': %v", hostport, err))
|
err = fmt.Errorf("no resolver '%s': %v", hostPort, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
|
|
@ -333,7 +372,8 @@ func (self *Api) getPath(uri string) (reader SectionReader, mimeType string, sta
|
||||||
var key Key
|
var key Key
|
||||||
key, err = self.Resolve(hostPort)
|
key, err = self.Resolve(hostPort)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
dpaLogger.Debugf("Swarm: rResolve error: %v", err)
|
err = errResolve(err)
|
||||||
|
dpaLogger.Debugf("Swarm: error : %v", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -352,7 +392,8 @@ func (self *Api) getPath(uri string) (reader SectionReader, mimeType string, sta
|
||||||
dpaLogger.Debugf("Swarm: content lookup key: '%064x' (%v)", key, mimeType)
|
dpaLogger.Debugf("Swarm: content lookup key: '%064x' (%v)", key, mimeType)
|
||||||
reader = self.dpa.Retrieve(key)
|
reader = self.dpa.Retrieve(key)
|
||||||
} else {
|
} else {
|
||||||
dpaLogger.Debugf("Swarm: getEntry(%s): not found", path)
|
err = fmt.Errorf("manifest entry for '%s' not found", path)
|
||||||
|
dpaLogger.Debugf("Swarm: %v", err)
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
||||||
114
bzz/api_test.go
114
bzz/api_test.go
|
|
@ -1,10 +1,112 @@
|
||||||
package bzz
|
package bzz
|
||||||
|
|
||||||
import (
|
import (
|
||||||
// "net/http"
|
"bytes"
|
||||||
// "strings"
|
"io/ioutil"
|
||||||
// "testing"
|
"os"
|
||||||
// "time"
|
"path"
|
||||||
|
"runtime"
|
||||||
// "github.com/ethereum/go-ethereum/common/docserver"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
testDir string
|
||||||
|
datadir = "/tmp/bzz"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
_, filename, _, _ := runtime.Caller(1)
|
||||||
|
testDir = path.Join(path.Dir(filename), "bzztest")
|
||||||
|
}
|
||||||
|
|
||||||
|
func testApi() (api *Api, err error) {
|
||||||
|
os.RemoveAll(datadir)
|
||||||
|
api, err = NewLocalApi(datadir)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
api.Start(nil, nil)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestApiPut(t *testing.T) {
|
||||||
|
api, err := testApi()
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("unexpected error: %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
expContent := "hello"
|
||||||
|
expMimeType := "text/plain"
|
||||||
|
expStatus := 0
|
||||||
|
expSize := len(expContent)
|
||||||
|
bzzhash, err := api.Put(expContent, expMimeType)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("unexpected error: %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
testGet(t, api, bzzhash, []byte(expContent), expMimeType, expStatus, expSize)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testGet(t *testing.T, api *Api, bzzhash string, expContent []byte, expMimeType string, expStatus int, expSize int) {
|
||||||
|
content, mimeType, status, size, err := api.Get(bzzhash)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("unexpected error: %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if !bytes.Equal(content, expContent) {
|
||||||
|
t.Errorf("incorrect content. expected '%s...', got '%s...'", string(expContent), string(content))
|
||||||
|
}
|
||||||
|
if mimeType != expMimeType {
|
||||||
|
t.Errorf("incorrect mimeType. expected '%s', got '%s'", expMimeType, mimeType)
|
||||||
|
}
|
||||||
|
if status != expStatus {
|
||||||
|
t.Errorf("incorrect status. expected '%d', got '%d'", expStatus, status)
|
||||||
|
}
|
||||||
|
if size != expSize {
|
||||||
|
t.Errorf("incorrect size. expected '%d', got '%d'", expSize, size)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestApiDirUpload(t *testing.T) {
|
||||||
|
api, err := testApi()
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("unexpected error: %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
bzzhash, err := api.Upload(path.Join(testDir, "test0"))
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("unexpected error: %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
content, err := ioutil.ReadFile(path.Join(testDir, "test0", "index.html"))
|
||||||
|
testGet(t, api, path.Join(bzzhash, "index.html"), content, "text/html", 0, 202)
|
||||||
|
testGet(t, api, bzzhash, content, "text/html", 0, 202)
|
||||||
|
|
||||||
|
content, err = ioutil.ReadFile(path.Join(testDir, "test0", "index.css"))
|
||||||
|
testGet(t, api, path.Join(bzzhash, "index.css"), content, "text/plain", 0, 132)
|
||||||
|
|
||||||
|
content, err = ioutil.ReadFile(path.Join(testDir, "test0", "img", "logo.png"))
|
||||||
|
testGet(t, api, path.Join(bzzhash, "img", "logo.png"), content, "image/png", 0, 18136)
|
||||||
|
|
||||||
|
_, _, _, _, err = api.Get(bzzhash)
|
||||||
|
if err == nil {
|
||||||
|
t.Errorf("expected error: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestApiFileUpload(t *testing.T) {
|
||||||
|
api, err := testApi()
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("unexpected error: %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
bzzhash, err := api.Upload(path.Join(testDir, "test0", "index.html"))
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("unexpected error: %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
content, err := ioutil.ReadFile(path.Join(testDir, "test0", "index.html"))
|
||||||
|
testGet(t, api, path.Join(bzzhash), content, "text/html", 0, 202)
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@ delimiter='{"entries":[{'
|
||||||
|
|
||||||
if [ -f "$1" ]; then
|
if [ -f "$1" ]; then
|
||||||
hash=`wget -q -O- --post-file="$1" http://localhost:8500/raw`
|
hash=`wget -q -O- --post-file="$1" http://localhost:8500/raw`
|
||||||
mime=`file --mime-type -b "$1"`
|
mime=`mimetype -b "$1"`
|
||||||
wget -q -O- --post-data="$delimiter\"hash\":\"$hash\",\"contentType\":\"$mime\"}]}" http://localhost:8500/raw
|
wget -q -O- --post-data="$delimiter\"hash\":\"$hash\",\"contentType\":\"$mime\"}]}" http://localhost:8500/raw
|
||||||
echo
|
echo
|
||||||
|
|
||||||
|
|
@ -21,7 +21,7 @@ pushd "$bzzroot" > /dev/null
|
||||||
|
|
||||||
(for path in `find . -type f`
|
(for path in `find . -type f`
|
||||||
do
|
do
|
||||||
name=`echo "$path" | cut -c2-`
|
name=`echo "$path" | cut -c3-`
|
||||||
[ _`basename "$name"` = "_$INDEX" ] && name=`dirname "$name"`
|
[ _`basename "$name"` = "_$INDEX" ] && name=`dirname "$name"`
|
||||||
echo -n "$delimiter"
|
echo -n "$delimiter"
|
||||||
hash=`wget -q -O- --post-file="$path" http://localhost:8500/raw`
|
hash=`wget -q -O- --post-file="$path" http://localhost:8500/raw`
|
||||||
|
|
|
||||||
|
|
@ -59,6 +59,7 @@ func (js *jsre) adminBindings() {
|
||||||
cinfo.Set("stop", js.stopNatSpec)
|
cinfo.Set("stop", js.stopNatSpec)
|
||||||
cinfo.Set("newRegistry", js.newRegistry)
|
cinfo.Set("newRegistry", js.newRegistry)
|
||||||
cinfo.Set("get", js.getContractInfo)
|
cinfo.Set("get", js.getContractInfo)
|
||||||
|
cinfo.Set("saveInfo", js.saveInfo)
|
||||||
cinfo.Set("register", js.register)
|
cinfo.Set("register", js.register)
|
||||||
cinfo.Set("registerUrl", js.registerUrl)
|
cinfo.Set("registerUrl", js.registerUrl)
|
||||||
// cinfo.Set("verify", js.verify)
|
// cinfo.Set("verify", js.verify)
|
||||||
|
|
@ -678,12 +679,18 @@ func (js *jsre) waitForBlocks(call otto.FunctionCall) otto.Value {
|
||||||
}
|
}
|
||||||
|
|
||||||
if args == 0 {
|
if args == 0 {
|
||||||
height = js.xeth.CurrentBlock().Number()
|
height = new(big.Int).Add(js.xeth.CurrentBlock().Number(), common.Big1)
|
||||||
height.Add(height, common.Big1)
|
|
||||||
}
|
}
|
||||||
|
height, err = waitForBlocks(js.wait, height, timer)
|
||||||
|
if err != nil {
|
||||||
|
return otto.UndefinedValue()
|
||||||
|
}
|
||||||
|
v, _ := call.Otto.ToValue(height.Uint64())
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
|
||||||
wait := js.wait
|
func waitForBlocks(wait chan *big.Int, height *big.Int, timer <-chan time.Time) (newHeight *big.Int, err error) {
|
||||||
js.wait <- height
|
wait <- height
|
||||||
select {
|
select {
|
||||||
case <-timer:
|
case <-timer:
|
||||||
// if times out make sure the xeth loop does not block
|
// if times out make sure the xeth loop does not block
|
||||||
|
|
@ -693,11 +700,10 @@ func (js *jsre) waitForBlocks(call otto.FunctionCall) otto.Value {
|
||||||
case <-wait:
|
case <-wait:
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
return otto.UndefinedValue()
|
return nil, fmt.Errorf("timeout")
|
||||||
case height = <-wait:
|
case newHeight = <-wait:
|
||||||
}
|
}
|
||||||
v, _ := call.Otto.ToValue(height.Uint64())
|
return
|
||||||
return v
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (js *jsre) sleep(call otto.FunctionCall) otto.Value {
|
func (js *jsre) sleep(call otto.FunctionCall) otto.Value {
|
||||||
|
|
@ -729,23 +735,49 @@ func (js *jsre) setSolc(call otto.FunctionCall) otto.Value {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (js *jsre) register(call otto.FunctionCall) otto.Value {
|
func (js *jsre) register(call otto.FunctionCall) otto.Value {
|
||||||
if len(call.ArgumentList) != 4 {
|
if len(call.ArgumentList) != 3 {
|
||||||
fmt.Println("requires 4 arguments: admin.contractInfo.register(fromaddress, contractaddress, contract, filename)")
|
fmt.Println("requires 3 arguments: admin.contractInfo.register(fromaddress, contractaddress, contenthash)")
|
||||||
return otto.UndefinedValue()
|
return otto.FalseValue()
|
||||||
}
|
}
|
||||||
sender, err := call.Argument(0).ToString()
|
sender, err := call.Argument(0).ToString()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println(err)
|
fmt.Println(err)
|
||||||
return otto.UndefinedValue()
|
return otto.FalseValue()
|
||||||
}
|
}
|
||||||
|
|
||||||
address, err := call.Argument(1).ToString()
|
address, err := call.Argument(1).ToString()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println(err)
|
fmt.Println(err)
|
||||||
return otto.UndefinedValue()
|
return otto.FalseValue()
|
||||||
}
|
}
|
||||||
|
|
||||||
raw, err := call.Argument(2).Export()
|
contentHashHex, err := call.Argument(2).ToString()
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
return otto.FalseValue()
|
||||||
|
}
|
||||||
|
|
||||||
|
// sender and contract address are passed as hex strings
|
||||||
|
codeb := js.xeth.CodeAtBytes(address)
|
||||||
|
codeHash := common.BytesToHash(crypto.Sha3(codeb))
|
||||||
|
contentHash := common.HexToHash(contentHashHex)
|
||||||
|
registry := resolver.New(js.xeth)
|
||||||
|
|
||||||
|
_, err = registry.RegisterContentHash(common.HexToAddress(sender), codeHash, contentHash)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
return otto.FalseValue()
|
||||||
|
}
|
||||||
|
|
||||||
|
return otto.TrueValue()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (js *jsre) saveInfo(call otto.FunctionCall) otto.Value {
|
||||||
|
if len(call.ArgumentList) != 2 {
|
||||||
|
fmt.Println("requires 2 arguments: admin.contractInfo.saveInfo(contract.info, filename)")
|
||||||
|
return otto.UndefinedValue()
|
||||||
|
}
|
||||||
|
raw, err := call.Argument(0).Export()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println(err)
|
fmt.Println(err)
|
||||||
return otto.UndefinedValue()
|
return otto.UndefinedValue()
|
||||||
|
|
@ -755,36 +787,20 @@ func (js *jsre) register(call otto.FunctionCall) otto.Value {
|
||||||
fmt.Println(err)
|
fmt.Println(err)
|
||||||
return otto.UndefinedValue()
|
return otto.UndefinedValue()
|
||||||
}
|
}
|
||||||
var contract compiler.Contract
|
var contractInfo compiler.ContractInfo
|
||||||
err = json.Unmarshal(jsonraw, &contract)
|
err = json.Unmarshal(jsonraw, &contractInfo)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println(err)
|
fmt.Println(err)
|
||||||
return otto.UndefinedValue()
|
return otto.UndefinedValue()
|
||||||
}
|
}
|
||||||
|
|
||||||
filename, err := call.Argument(3).ToString()
|
filename, err := call.Argument(1).ToString()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println(err)
|
fmt.Println(err)
|
||||||
return otto.UndefinedValue()
|
return otto.UndefinedValue()
|
||||||
}
|
}
|
||||||
|
|
||||||
contenthash, err := compiler.ExtractInfo(&contract, filename)
|
contenthash, err := compiler.SaveInfo(&contractInfo, filename)
|
||||||
if err != nil {
|
|
||||||
fmt.Println(err)
|
|
||||||
return otto.UndefinedValue()
|
|
||||||
}
|
|
||||||
// sender and contract address are passed as hex strings
|
|
||||||
codeb := js.xeth.CodeAtBytes(address)
|
|
||||||
codehash := common.BytesToHash(crypto.Sha3(codeb))
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println(err)
|
|
||||||
return otto.UndefinedValue()
|
|
||||||
}
|
|
||||||
|
|
||||||
registry := resolver.New(js.xeth)
|
|
||||||
|
|
||||||
_, err = registry.RegisterContentHash(common.HexToAddress(sender), codehash, contenthash)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println(err)
|
fmt.Println(err)
|
||||||
return otto.UndefinedValue()
|
return otto.UndefinedValue()
|
||||||
|
|
@ -796,7 +812,7 @@ func (js *jsre) register(call otto.FunctionCall) otto.Value {
|
||||||
|
|
||||||
func (js *jsre) registerUrl(call otto.FunctionCall) otto.Value {
|
func (js *jsre) registerUrl(call otto.FunctionCall) otto.Value {
|
||||||
if len(call.ArgumentList) != 3 {
|
if len(call.ArgumentList) != 3 {
|
||||||
fmt.Println("requires 3 arguments: admin.contractInfo.register(fromaddress, contenthash, filename)")
|
fmt.Println("requires 3 arguments: admin.contractInfo.registerUrl(fromaddress, contenthash, url)")
|
||||||
return otto.FalseValue()
|
return otto.FalseValue()
|
||||||
}
|
}
|
||||||
sender, err := call.Argument(0).ToString()
|
sender, err := call.Argument(0).ToString()
|
||||||
|
|
@ -818,7 +834,6 @@ func (js *jsre) registerUrl(call otto.FunctionCall) otto.Value {
|
||||||
}
|
}
|
||||||
|
|
||||||
registry := resolver.New(js.xeth)
|
registry := resolver.New(js.xeth)
|
||||||
|
|
||||||
_, err = registry.RegisterUrl(common.HexToAddress(sender), common.HexToHash(contenthash), url)
|
_, err = registry.RegisterUrl(common.HexToAddress(sender), common.HexToHash(contenthash), url)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println(err)
|
fmt.Println(err)
|
||||||
|
|
@ -830,7 +845,7 @@ func (js *jsre) registerUrl(call otto.FunctionCall) otto.Value {
|
||||||
|
|
||||||
func (js *jsre) getContractInfo(call otto.FunctionCall) otto.Value {
|
func (js *jsre) getContractInfo(call otto.FunctionCall) otto.Value {
|
||||||
if len(call.ArgumentList) != 1 {
|
if len(call.ArgumentList) != 1 {
|
||||||
fmt.Println("requires 1 argument: admin.contractInfo.register(contractaddress)")
|
fmt.Println("requires 1 argument: admin.contractInfo.get(contractaddress)")
|
||||||
return otto.FalseValue()
|
return otto.FalseValue()
|
||||||
}
|
}
|
||||||
addr, err := call.Argument(0).ToString()
|
addr, err := call.Argument(0).ToString()
|
||||||
|
|
|
||||||
|
|
@ -85,6 +85,7 @@ func newJSRE(ethereum *eth.Ethereum, libPath, corsDomain string, bzzEnabled bool
|
||||||
js.xeth = xeth.New(ethereum, f)
|
js.xeth = xeth.New(ethereum, f)
|
||||||
js.wait = js.xeth.UpdateState()
|
js.wait = js.xeth.UpdateState()
|
||||||
js.re = re.New(libPath)
|
js.re = re.New(libPath)
|
||||||
|
// js.apiBindings(js.xeth)
|
||||||
js.apiBindings(f)
|
js.apiBindings(f)
|
||||||
js.adminBindings()
|
js.adminBindings()
|
||||||
if bzzEnabled {
|
if bzzEnabled {
|
||||||
|
|
@ -113,6 +114,7 @@ func newJSRE(ethereum *eth.Ethereum, libPath, corsDomain string, bzzEnabled bool
|
||||||
|
|
||||||
func (js *jsre) apiBindings(f xeth.Frontend) {
|
func (js *jsre) apiBindings(f xeth.Frontend) {
|
||||||
xe := xeth.New(js.ethereum, f)
|
xe := xeth.New(js.ethereum, f)
|
||||||
|
// func (js *jsre) apiBindings(xe *xeth.XEth) {
|
||||||
ethApi := rpc.NewEthereumApi(xe)
|
ethApi := rpc.NewEthereumApi(xe)
|
||||||
jeth := rpc.NewJeth(ethApi, js.re)
|
jeth := rpc.NewJeth(ethApi, js.re)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,12 +3,14 @@ package main
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
|
"math/big"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"regexp"
|
"regexp"
|
||||||
"runtime"
|
"runtime"
|
||||||
"strconv"
|
"strconv"
|
||||||
"testing"
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/accounts"
|
"github.com/ethereum/go-ethereum/accounts"
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
|
|
@ -17,7 +19,6 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/common/natspec"
|
"github.com/ethereum/go-ethereum/common/natspec"
|
||||||
"github.com/ethereum/go-ethereum/common/resolver"
|
"github.com/ethereum/go-ethereum/common/resolver"
|
||||||
"github.com/ethereum/go-ethereum/core"
|
"github.com/ethereum/go-ethereum/core"
|
||||||
"github.com/ethereum/go-ethereum/core/state"
|
|
||||||
"github.com/ethereum/go-ethereum/crypto"
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
"github.com/ethereum/go-ethereum/eth"
|
"github.com/ethereum/go-ethereum/eth"
|
||||||
)
|
)
|
||||||
|
|
@ -41,7 +42,6 @@ var (
|
||||||
|
|
||||||
type testjethre struct {
|
type testjethre struct {
|
||||||
*jsre
|
*jsre
|
||||||
stateDb *state.StateDB
|
|
||||||
lastConfirm string
|
lastConfirm string
|
||||||
ds *docserver.DocServer
|
ds *docserver.DocServer
|
||||||
}
|
}
|
||||||
|
|
@ -79,6 +79,7 @@ func testJEthRE(t *testing.T) (string, *testjethre, *eth.Ethereum) {
|
||||||
MaxPeers: 0,
|
MaxPeers: 0,
|
||||||
Name: "test",
|
Name: "test",
|
||||||
SolcPath: testSolcPath,
|
SolcPath: testSolcPath,
|
||||||
|
PowTest: true,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal("%v", err)
|
t.Fatal("%v", err)
|
||||||
|
|
@ -101,19 +102,12 @@ func testJEthRE(t *testing.T) (string, *testjethre, *eth.Ethereum) {
|
||||||
|
|
||||||
assetPath := filepath.Join(os.Getenv("GOPATH"), "src", "github.com", "ethereum", "go-ethereum", "cmd", "mist", "assets", "ext")
|
assetPath := filepath.Join(os.Getenv("GOPATH"), "src", "github.com", "ethereum", "go-ethereum", "cmd", "mist", "assets", "ext")
|
||||||
ds := docserver.New("/")
|
ds := docserver.New("/")
|
||||||
tf := &testjethre{ds: ds, stateDb: ethereum.ChainManager().State().Copy()}
|
tf := &testjethre{ds: ds}
|
||||||
repl := newJSRE(ethereum, assetPath, "", false, "", false, tf)
|
repl := newJSRE(ethereum, assetPath, "", false, "", false, tf)
|
||||||
tf.jsre = repl
|
tf.jsre = repl
|
||||||
return tmp, tf, ethereum
|
return tmp, tf, ethereum
|
||||||
}
|
}
|
||||||
|
|
||||||
// this line below is needed for transaction to be applied to the state in testing
|
|
||||||
// the heavy lifing is done in XEth.ApplyTestTxs
|
|
||||||
// this is fragile, overwriting xeth will result in
|
|
||||||
// process leaking since xeth loops cannot quit safely
|
|
||||||
// should be replaced by proper mining with testDAG for easy full integration tests
|
|
||||||
// txc, self.xeth = self.xeth.ApplyTestTxs(self.xeth.repl.stateDb, coinbase, txc)
|
|
||||||
|
|
||||||
func TestNodeInfo(t *testing.T) {
|
func TestNodeInfo(t *testing.T) {
|
||||||
t.Skip("broken after p2p update")
|
t.Skip("broken after p2p update")
|
||||||
tmp, repl, ethereum := testJEthRE(t)
|
tmp, repl, ethereum := testJEthRE(t)
|
||||||
|
|
@ -257,12 +251,9 @@ func TestContract(t *testing.T) {
|
||||||
defer ethereum.Stop()
|
defer ethereum.Stop()
|
||||||
defer os.RemoveAll(tmp)
|
defer os.RemoveAll(tmp)
|
||||||
|
|
||||||
var txc uint64
|
|
||||||
coinbase := common.HexToAddress(testAddress)
|
coinbase := common.HexToAddress(testAddress)
|
||||||
resolver.New(repl.xeth).CreateContracts(coinbase)
|
resolver.New(repl.xeth).CreateContracts(coinbase)
|
||||||
// time.Sleep(1000 * time.Millisecond)
|
|
||||||
|
|
||||||
// checkEvalJSON(t, repl, `eth.getBlock("pending", true).transactions.length`, `2`)
|
|
||||||
source := `contract test {\n` +
|
source := `contract test {\n` +
|
||||||
" /// @notice Will multiply `a` by 7." + `\n` +
|
" /// @notice Will multiply `a` by 7." + `\n` +
|
||||||
` function multiply(uint a) returns(uint d) {\n` +
|
` function multiply(uint a) returns(uint d) {\n` +
|
||||||
|
|
@ -270,14 +261,20 @@ func TestContract(t *testing.T) {
|
||||||
` }\n` +
|
` }\n` +
|
||||||
`}\n`
|
`}\n`
|
||||||
|
|
||||||
checkEvalJSON(t, repl, `admin.contractInfo.stop()`, `true`)
|
if checkEvalJSON(t, repl, `admin.contractInfo.stop()`, `true`) != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
contractInfo, err := ioutil.ReadFile("info_test.json")
|
contractInfo, err := ioutil.ReadFile("info_test.json")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("%v", err)
|
t.Fatalf("%v", err)
|
||||||
}
|
}
|
||||||
checkEvalJSON(t, repl, `primary = eth.accounts[0]`, `"`+testAddress+`"`)
|
if checkEvalJSON(t, repl, `primary = eth.accounts[0]`, `"`+testAddress+`"`) != nil {
|
||||||
checkEvalJSON(t, repl, `source = "`+source+`"`, `"`+source+`"`)
|
return
|
||||||
|
}
|
||||||
|
if checkEvalJSON(t, repl, `source = "`+source+`"`, `"`+source+`"`) != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// if solc is found with right version, test it, otherwise read from file
|
// if solc is found with right version, test it, otherwise read from file
|
||||||
sol, err := compiler.New("")
|
sol, err := compiler.New("")
|
||||||
|
|
@ -297,71 +294,156 @@ func TestContract(t *testing.T) {
|
||||||
t.Errorf("%v", err)
|
t.Errorf("%v", err)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
checkEvalJSON(t, repl, `contract = eth.compile.solidity(source).test`, string(contractInfo))
|
if checkEvalJSON(t, repl, `contract = eth.compile.solidity(source).test`, string(contractInfo)) != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
checkEvalJSON(t, repl, `contract.code`, `"0x605880600c6000396000f3006000357c010000000000000000000000000000000000000000000000000000000090048063c6888fa114602e57005b603d6004803590602001506047565b8060005260206000f35b60006007820290506053565b91905056"`)
|
if checkEvalJSON(t, repl, `contract.code`, `"0x605880600c6000396000f3006000357c010000000000000000000000000000000000000000000000000000000090048063c6888fa114602e57005b603d6004803590602001506047565b8060005260206000f35b60006007820290506053565b91905056"`) != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
checkEvalJSON(
|
if checkEvalJSON(
|
||||||
t, repl,
|
t, repl,
|
||||||
`contractaddress = eth.sendTransaction({from: primary, data: contract.code })`,
|
`contractaddress = eth.sendTransaction({from: primary, data: contract.code, gasPrice:"1000", gas:"100000", amount:100 })`,
|
||||||
`"0x291293d57e0a0ab47effe97c02577f90d9211567"`,
|
`"0x291293d57e0a0ab47effe97c02577f90d9211567"`,
|
||||||
)
|
) != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if !processTxs(repl, t, 7) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
callSetup := `abiDef = JSON.parse('[{"constant":false,"inputs":[{"name":"a","type":"uint256"}],"name":"multiply","outputs":[{"name":"d","type":"uint256"}],"type":"function"}]');
|
callSetup := `abiDef = JSON.parse('[{"constant":false,"inputs":[{"name":"a","type":"uint256"}],"name":"multiply","outputs":[{"name":"d","type":"uint256"}],"type":"function"}]');
|
||||||
Multiply7 = eth.contract(abiDef);
|
Multiply7 = eth.contract(abiDef);
|
||||||
multiply7 = Multiply7.at(contractaddress);
|
multiply7 = Multiply7.at(contractaddress);
|
||||||
`
|
`
|
||||||
// time.Sleep(1500 * time.Millisecond)
|
|
||||||
_, err = repl.re.Run(callSetup)
|
_, err = repl.re.Run(callSetup)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("unexpected error setting up contract, got %v", err)
|
t.Errorf("unexpected error setting up contract, got %v", err)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// checkEvalJSON(t, repl, `eth.getBlock("pending", true).transactions.length`, `3`)
|
|
||||||
|
|
||||||
// why is this sometimes failing?
|
|
||||||
// checkEvalJSON(t, repl, `multiply7.multiply.call(6)`, `42`)
|
|
||||||
expNotice := ""
|
expNotice := ""
|
||||||
if repl.lastConfirm != expNotice {
|
if repl.lastConfirm != expNotice {
|
||||||
t.Errorf("incorrect confirmation message: expected %v, got %v", expNotice, repl.lastConfirm)
|
t.Errorf("incorrect confirmation message: expected %v, got %v", expNotice, repl.lastConfirm)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
txc, repl.xeth = repl.xeth.ApplyTestTxs(repl.stateDb, coinbase, txc)
|
if checkEvalJSON(t, repl, `admin.contractInfo.start()`, `true`) != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if checkEvalJSON(t, repl, `multiply7.multiply.sendTransaction(6, { from: primary })`, `undefined`) != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if !processTxs(repl, t, 1) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
checkEvalJSON(t, repl, `admin.contractInfo.start()`, `true`)
|
|
||||||
checkEvalJSON(t, repl, `multiply7.multiply.sendTransaction(6, { from: primary, gas: "1000000", gasPrice: "100000" })`, `undefined`)
|
|
||||||
expNotice = `About to submit transaction (no NatSpec info found for contract: content hash not found for '0x87e2802265838c7f14bb69eecd2112911af6767907a702eeaa445239fb20711b'): {"params":[{"to":"0x291293d57e0a0ab47effe97c02577f90d9211567","data": "0xc6888fa10000000000000000000000000000000000000000000000000000000000000006"}]}`
|
expNotice = `About to submit transaction (no NatSpec info found for contract: content hash not found for '0x87e2802265838c7f14bb69eecd2112911af6767907a702eeaa445239fb20711b'): {"params":[{"to":"0x291293d57e0a0ab47effe97c02577f90d9211567","data": "0xc6888fa10000000000000000000000000000000000000000000000000000000000000006"}]}`
|
||||||
if repl.lastConfirm != expNotice {
|
if repl.lastConfirm != expNotice {
|
||||||
t.Errorf("incorrect confirmation message: expected %v, got %v", expNotice, repl.lastConfirm)
|
t.Errorf("incorrect confirmation message: expected\n%v, got\n%v", expNotice, repl.lastConfirm)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
var contenthash = `"0x86d2b7cf1e72e9a7a3f8d96601f0151742a2f780f1526414304fbe413dc7f9bd"`
|
var contentHash = `"0x86d2b7cf1e72e9a7a3f8d96601f0151742a2f780f1526414304fbe413dc7f9bd"`
|
||||||
if sol != nil {
|
if sol != nil && solcVersion != sol.Version() {
|
||||||
modContractInfo := versionRE.ReplaceAll(contractInfo, []byte(`"compilerVersion":"`+sol.Version()+`"`))
|
modContractInfo := versionRE.ReplaceAll(contractInfo, []byte(`"compilerVersion":"`+sol.Version()+`"`))
|
||||||
_ = modContractInfo
|
fmt.Printf("modified contractinfo:\n%s\n", modContractInfo)
|
||||||
// contenthash = crypto.Sha3(modContractInfo)
|
contentHash = `"` + common.ToHex(crypto.Sha3([]byte(modContractInfo))) + `"`
|
||||||
}
|
}
|
||||||
checkEvalJSON(t, repl, `filename = "/tmp/info.json"`, `"/tmp/info.json"`)
|
if checkEvalJSON(t, repl, `filename = "/tmp/info.json"`, `"/tmp/info.json"`) != nil {
|
||||||
checkEvalJSON(t, repl, `contenthash = admin.contractInfo.register(primary, contractaddress, contract, filename)`, contenthash)
|
return
|
||||||
checkEvalJSON(t, repl, `admin.contractInfo.registerUrl(primary, contenthash, "file://"+filename)`, `true`)
|
}
|
||||||
if err != nil {
|
if checkEvalJSON(t, repl, `contentHash = admin.contractInfo.saveInfo(contract.info, filename)`, contentHash) != nil {
|
||||||
t.Errorf("unexpected error registering, got %v", err)
|
return
|
||||||
|
}
|
||||||
|
if checkEvalJSON(t, repl, `admin.contractInfo.register(primary, contractaddress, contentHash)`, `true`) != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if checkEvalJSON(t, repl, `admin.contractInfo.registerUrl(primary, contentHash, "file://"+filename)`, `true`) != nil {
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
checkEvalJSON(t, repl, `admin.contractInfo.start()`, `true`)
|
if checkEvalJSON(t, repl, `admin.contractInfo.start()`, `true`) != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// update state
|
if !processTxs(repl, t, 3) {
|
||||||
txc, repl.xeth = repl.xeth.ApplyTestTxs(repl.stateDb, coinbase, txc)
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if checkEvalJSON(t, repl, `multiply7.multiply.sendTransaction(6, { from: primary })`, `undefined`) != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if !processTxs(repl, t, 1) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
checkEvalJSON(t, repl, `multiply7.multiply.sendTransaction(6, { from: primary, gas: "1000000", gasPrice: "100000" })`, `undefined`)
|
|
||||||
expNotice = "Will multiply 6 by 7."
|
expNotice = "Will multiply 6 by 7."
|
||||||
if repl.lastConfirm != expNotice {
|
if repl.lastConfirm != expNotice {
|
||||||
t.Errorf("incorrect confirmation message: expected %v, got %v", expNotice, repl.lastConfirm)
|
t.Errorf("incorrect confirmation message: expected\n%v, got\n%v", expNotice, repl.lastConfirm)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func pendingTransactions(repl *testjethre, t *testing.T) (txc int64, err error) {
|
||||||
|
txs := repl.ethereum.TxPool().GetTransactions()
|
||||||
|
return int64(len(txs)), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func processTxs(repl *testjethre, t *testing.T, expTxc int) bool {
|
||||||
|
var txc int64
|
||||||
|
var err error
|
||||||
|
for i := 0; i < 50; i++ {
|
||||||
|
txc, err = pendingTransactions(repl, t)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("unexpected error checking pending transactions: %v", err)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if expTxc < int(txc) {
|
||||||
|
t.Errorf("too many pending transactions: expected %v, got %v", expTxc, txc)
|
||||||
|
return false
|
||||||
|
} else if expTxc == int(txc) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
time.Sleep(100 * time.Millisecond)
|
||||||
|
}
|
||||||
|
if int(txc) != expTxc {
|
||||||
|
t.Errorf("incorrect number of pending transactions, expected %v, got %v", expTxc, txc)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
err = repl.ethereum.StartMining(runtime.NumCPU())
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("unexpected error mining: %v", err)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
defer repl.ethereum.StopMining()
|
||||||
|
|
||||||
|
timer := time.NewTimer(100 * time.Second)
|
||||||
|
height := new(big.Int).Add(repl.xeth.CurrentBlock().Number(), big.NewInt(1))
|
||||||
|
_, err = waitForBlocks(repl.wait, height, timer.C)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("error mining transactions: %v", err)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
txc, err = pendingTransactions(repl, t)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("unexpected error checking pending transactions: %v", err)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if txc != 0 {
|
||||||
|
t.Errorf("%d trasactions were not mined", txc)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
func checkEvalJSON(t *testing.T, re *testjethre, expr, want string) error {
|
func checkEvalJSON(t *testing.T, re *testjethre, expr, want string) error {
|
||||||
val, err := re.re.Run("JSON.stringify(" + expr + ")")
|
val, err := re.re.Run("JSON.stringify(" + expr + ")")
|
||||||
if err == nil && val.String() != want {
|
if err == nil && val.String() != want {
|
||||||
|
|
|
||||||
|
|
@ -185,12 +185,12 @@ func (sol *Solidity) Compile(source string) (contracts map[string]*Contract, err
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func ExtractInfo(contract *Contract, filename string) (contenthash common.Hash, err error) {
|
func SaveInfo(info *ContractInfo, filename string) (contenthash common.Hash, err error) {
|
||||||
contractInfo, err := json.Marshal(contract.Info)
|
infojson, err := json.Marshal(info)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
contenthash = common.BytesToHash(crypto.Sha3(contractInfo))
|
contenthash = common.BytesToHash(crypto.Sha3(infojson))
|
||||||
err = ioutil.WriteFile(filename, contractInfo, 0600)
|
err = ioutil.WriteFile(filename, infojson, 0600)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -72,19 +72,15 @@ func TestNoCompiler(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestExtractInfo(t *testing.T) {
|
func TestSaveInfo(t *testing.T) {
|
||||||
var cinfo ContractInfo
|
var cinfo *ContractInfo
|
||||||
err := json.Unmarshal([]byte(info), &cinfo)
|
err := json.Unmarshal([]byte(info), cinfo)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("%v", err)
|
t.Errorf("%v", err)
|
||||||
}
|
}
|
||||||
contract := &Contract{
|
|
||||||
Code: "",
|
|
||||||
Info: cinfo,
|
|
||||||
}
|
|
||||||
filename := "/tmp/solctest.info.json"
|
filename := "/tmp/solctest.info.json"
|
||||||
os.Remove(filename)
|
os.Remove(filename)
|
||||||
cinfohash, err := ExtractInfo(contract, filename)
|
cinfohash, err := SaveInfo(cinfo, filename)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("error extracting info: %v", err)
|
t.Errorf("error extracting info: %v", err)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -36,8 +36,8 @@ var (
|
||||||
|
|
||||||
const (
|
const (
|
||||||
txValue = "0"
|
txValue = "0"
|
||||||
txGas = "100000"
|
txGas = ""
|
||||||
txGasPrice = "1000000000000"
|
txGasPrice = ""
|
||||||
)
|
)
|
||||||
|
|
||||||
func abiSignature(s string) string {
|
func abiSignature(s string) string {
|
||||||
|
|
@ -284,7 +284,7 @@ func (self *Resolver) RegisterUrl(address common.Address, hash common.Hash, url
|
||||||
// registers key -> conenthash in HashReg and
|
// registers key -> conenthash in HashReg and
|
||||||
// registers contenthash -> url in UrlHint
|
// registers contenthash -> url in UrlHint
|
||||||
// creates 3 transaction using address as sender
|
// creates 3 transaction using address as sender
|
||||||
// transactions need to obe mined to take effect
|
// transactions need to be mined to take effect
|
||||||
func (self *Resolver) RegisterAddrWithUrl(address common.Address, codehash, dochash common.Hash, url string) (txh string, err error) {
|
func (self *Resolver) RegisterAddrWithUrl(address common.Address, codehash, dochash common.Hash, url string) (txh string, err error) {
|
||||||
|
|
||||||
_, err = self.RegisterContentHash(address, codehash, dochash)
|
_, err = self.RegisterContentHash(address, codehash, dochash)
|
||||||
|
|
|
||||||
|
|
@ -231,6 +231,9 @@ func (tp *TxPool) GetTransaction(hash common.Hash) *types.Transaction {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *TxPool) GetTransactions() (txs types.Transactions) {
|
func (self *TxPool) GetTransactions() (txs types.Transactions) {
|
||||||
|
self.checkQueue()
|
||||||
|
self.validatePool()
|
||||||
|
|
||||||
self.mu.RLock()
|
self.mu.RLock()
|
||||||
defer self.mu.RUnlock()
|
defer self.mu.RUnlock()
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -88,6 +88,7 @@ type Config struct {
|
||||||
Dial bool
|
Dial bool
|
||||||
Bzz bool
|
Bzz bool
|
||||||
BzzPort string
|
BzzPort string
|
||||||
|
PowTest bool
|
||||||
|
|
||||||
Etherbase string
|
Etherbase string
|
||||||
GasPrice *big.Int
|
GasPrice *big.Int
|
||||||
|
|
@ -288,7 +289,15 @@ func New(config *Config) (*Ethereum, error) {
|
||||||
AutoDAG: config.AutoDAG,
|
AutoDAG: config.AutoDAG,
|
||||||
}
|
}
|
||||||
|
|
||||||
eth.pow = ethash.New()
|
if config.PowTest {
|
||||||
|
glog.V(logger.Info).Infof("ethash used in test mode")
|
||||||
|
eth.pow, err = ethash.NewForTesting()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
eth.pow = ethash.New()
|
||||||
|
}
|
||||||
eth.chainManager = core.NewChainManager(blockDb, stateDb, eth.pow, eth.EventMux())
|
eth.chainManager = core.NewChainManager(blockDb, stateDb, eth.pow, eth.EventMux())
|
||||||
eth.downloader = downloader.New(eth.EventMux(), eth.chainManager.HasBlock, eth.chainManager.GetBlock)
|
eth.downloader = downloader.New(eth.EventMux(), eth.chainManager.HasBlock, eth.chainManager.GetBlock)
|
||||||
eth.txPool = core.NewTxPool(eth.EventMux(), eth.chainManager.State, eth.chainManager.GasLimit)
|
eth.txPool = core.NewTxPool(eth.EventMux(), eth.chainManager.State, eth.chainManager.GasLimit)
|
||||||
|
|
@ -312,11 +321,17 @@ func New(config *Config) (*Ethereum, error) {
|
||||||
|
|
||||||
if config.Bzz {
|
if config.Bzz {
|
||||||
eth.Swarm, err = bzz.NewApi(config.DataDir, config.BzzPort)
|
eth.Swarm, err = bzz.NewApi(config.DataDir, config.BzzPort)
|
||||||
var proto p2p.Protocol
|
if err != nil {
|
||||||
proto, err = eth.Swarm.Bzz()
|
|
||||||
if err == nil {
|
|
||||||
glog.V(logger.Warn).Infof("BZZ: error creating swarm: %v. Protocol skipped", err)
|
glog.V(logger.Warn).Infof("BZZ: error creating swarm: %v. Protocol skipped", err)
|
||||||
protocols = append(protocols, proto)
|
} else {
|
||||||
|
var proto p2p.Protocol
|
||||||
|
proto, err = eth.Swarm.Bzz()
|
||||||
|
if err != nil {
|
||||||
|
glog.V(logger.Warn).Infof("BZZ: error creating swarm: %v. Protocol skipped", err)
|
||||||
|
eth.Swarm = nil
|
||||||
|
} else {
|
||||||
|
protocols = append(protocols, proto)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue