Merge branch 'master' into swarm-rather-stable

Conflicts were in:
	swarm/api/http/test_server.go
	swarm/storage/ldbstore_test.go
from 26b50e3ebe
This commit is contained in:
Ferenc Szabo 2019-04-11 17:42:16 +02:00
commit 432349a93a
15 changed files with 577 additions and 95 deletions

File diff suppressed because one or more lines are too long

273
cmd/clef/bindata.go Normal file

File diff suppressed because one or more lines are too long

View file

@ -18,6 +18,9 @@
// arbitrary data. // arbitrary data.
package main package main
//go:generate go-bindata -o bindata.go resources/4byte.json
//go:generate gofmt -s -w bindata.go
import ( import (
"bufio" "bufio"
"context" "context"
@ -57,14 +60,17 @@ import (
) )
const legalWarning = ` const legalWarning = `
WARNING! WARNING!
Clef is alpha software, and not yet publically released. This software has _not_ been audited, and there Clef is an account management tool. It may, like any software, contain bugs.
are no guarantees about the workings of this software. It may contain severe flaws. You should not use this software
unless you agree to take full responsibility for doing so, and know what you are doing.
TLDR; THIS IS NOT PRODUCTION-READY SOFTWARE! Please take care to
- backup your keystore files,
- verify that the keystore(s) can be opened with your password.
Clef 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.
` `
var ( var (
@ -101,11 +107,6 @@ var (
Name: "signersecret", Name: "signersecret",
Usage: "A file containing the (encrypted) master seed to encrypt Clef data, e.g. keystore credentials and ruleset hash", Usage: "A file containing the (encrypted) master seed to encrypt Clef data, e.g. keystore credentials and ruleset hash",
} }
dBFlag = cli.StringFlag{
Name: "4bytedb",
Usage: "File containing 4byte-identifiers",
Value: "./4byte.json",
}
customDBFlag = cli.StringFlag{ customDBFlag = cli.StringFlag{
Name: "4bytedb-custom", Name: "4bytedb-custom",
Usage: "File used for writing new 4byte-identifiers submitted via API", Usage: "File used for writing new 4byte-identifiers submitted via API",
@ -142,7 +143,7 @@ var (
configdirFlag, configdirFlag,
}, },
Description: ` Description: `
The init command generates a master seed which Clef can use to store credentials and data needed for The init command generates a master seed which Clef can use to store credentials and data needed for
the rule-engine to work.`, the rule-engine to work.`,
} }
attestCommand = cli.Command{ attestCommand = cli.Command{
@ -156,10 +157,10 @@ the rule-engine to work.`,
signerSecretFlag, signerSecretFlag,
}, },
Description: ` Description: `
The attest command stores the sha256 of the rule.js-file that you want to use for automatic processing of The attest command stores the sha256 of the rule.js-file that you want to use for automatic processing of
incoming requests. incoming requests.
Whenever you make an edit to the rule file, you need to use attestation to tell Whenever you make an edit to the rule file, you need to use attestation to tell
Clef that the file is 'safe' to execute.`, Clef that the file is 'safe' to execute.`,
} }
@ -174,7 +175,7 @@ Clef that the file is 'safe' to execute.`,
signerSecretFlag, signerSecretFlag,
}, },
Description: ` Description: `
The setpw command stores a password for a given address (keyfile). If you enter a blank passphrase, it will The setpw command stores a password for a given address (keyfile). If you enter a blank passphrase, it will
remove any stored credential for that address (keyfile) remove any stored credential for that address (keyfile)
`} `}
gendocCommand = cli.Command{ gendocCommand = cli.Command{
@ -203,7 +204,6 @@ func init() {
utils.RPCEnabledFlag, utils.RPCEnabledFlag,
rpcPortFlag, rpcPortFlag,
signerSecretFlag, signerSecretFlag,
dBFlag,
customDBFlag, customDBFlag,
auditLogFlag, auditLogFlag,
ruleFlag, ruleFlag,
@ -270,12 +270,12 @@ func initializeSecrets(c *cli.Context) error {
} }
fmt.Printf("A master seed has been generated into %s\n", location) fmt.Printf("A master seed has been generated into %s\n", location)
fmt.Printf(` fmt.Printf(`
This is required to be able to store credentials, such as : This is required to be able to store credentials, such as :
* Passwords for keystores (used by rule engine) * Passwords for keystores (used by rule engine)
* Storage for javascript rules * Storage for javascript rules
* Hash of rule-file * Hash of rule-file
You should treat that file with utmost secrecy, and make a backup of it. You should treat that file with utmost secrecy, and make a backup of it.
NOTE: This file does not contain your accounts. Those need to be backed up separately! NOTE: This file does not contain your accounts. Those need to be backed up separately!
`) `)
@ -362,13 +362,17 @@ func signer(c *cli.Context) error {
log.Info("Using CLI as UI-channel") log.Info("Using CLI as UI-channel")
ui = core.NewCommandlineUI() ui = core.NewCommandlineUI()
} }
fourByteDb := c.GlobalString(dBFlag.Name) // 4bytedb data
fourByteLocal := c.GlobalString(customDBFlag.Name) fourByteLocal := c.GlobalString(customDBFlag.Name)
db, err := core.NewAbiDBFromFiles(fourByteDb, fourByteLocal) data, err := Asset("resources/4byte.json")
if err != nil { if err != nil {
utils.Fatalf(err.Error()) utils.Fatalf(err.Error())
} }
log.Info("Loaded 4byte db", "signatures", db.Size(), "file", fourByteDb, "local", fourByteLocal) db, err := core.NewAbiDBFromFiles(data, fourByteLocal)
if err != nil {
utils.Fatalf(err.Error())
}
log.Info("Loaded 4byte db", "signatures", db.Size(), "local", fourByteLocal)
var ( var (
api core.ExternalAPI api core.ExternalAPI

File diff suppressed because one or more lines are too long

View file

@ -52,11 +52,12 @@ func TestACT(t *testing.T) {
t.Skip() t.Skip()
} }
initCluster(t) cluster := newTestCluster(t, clusterSize)
defer cluster.Shutdown()
cases := []struct { cases := []struct {
name string name string
f func(t *testing.T) f func(t *testing.T, cluster *testCluster)
}{ }{
{"Password", testPassword}, {"Password", testPassword},
{"PK", testPK}, {"PK", testPK},
@ -65,7 +66,9 @@ func TestACT(t *testing.T) {
} }
for _, tc := range cases { for _, tc := range cases {
t.Run(tc.name, tc.f) t.Run(tc.name, func(t *testing.T) {
tc.f(t, cluster)
})
} }
} }
@ -74,7 +77,7 @@ func TestACT(t *testing.T) {
// The parties participating - node (publisher), uploads to second node then disappears. Content which was uploaded // The parties participating - node (publisher), uploads to second node then disappears. Content which was uploaded
// is then fetched through 2nd node. since the tested code is not key-aware - we can just // is then fetched through 2nd node. since the tested code is not key-aware - we can just
// fetch from the 2nd node using HTTP BasicAuth // fetch from the 2nd node using HTTP BasicAuth
func testPassword(t *testing.T) { func testPassword(t *testing.T, cluster *testCluster) {
dataFilename := testutil.TempFileWithContent(t, data) dataFilename := testutil.TempFileWithContent(t, data)
defer os.RemoveAll(dataFilename) defer os.RemoveAll(dataFilename)
@ -226,7 +229,7 @@ func testPassword(t *testing.T) {
// The parties participating - node (publisher), uploads to second node (which is also the grantee) then disappears. // The parties participating - node (publisher), uploads to second node (which is also the grantee) then disappears.
// Content which was uploaded is then fetched through the grantee's http proxy. Since the tested code is private-key aware, // Content which was uploaded is then fetched through the grantee's http proxy. Since the tested code is private-key aware,
// the test will fail if the proxy's given private key is not granted on the ACT. // the test will fail if the proxy's given private key is not granted on the ACT.
func testPK(t *testing.T) { func testPK(t *testing.T, cluster *testCluster) {
dataFilename := testutil.TempFileWithContent(t, data) dataFilename := testutil.TempFileWithContent(t, data)
defer os.RemoveAll(dataFilename) defer os.RemoveAll(dataFilename)
@ -359,13 +362,13 @@ func testPK(t *testing.T) {
} }
// testACTWithoutBogus tests the creation of the ACT manifest end-to-end, without any bogus entries (i.e. default scenario = 3 nodes 1 unauthorized) // testACTWithoutBogus tests the creation of the ACT manifest end-to-end, without any bogus entries (i.e. default scenario = 3 nodes 1 unauthorized)
func testACTWithoutBogus(t *testing.T) { func testACTWithoutBogus(t *testing.T, cluster *testCluster) {
testACT(t, 0) testACT(t, cluster, 0)
} }
// testACTWithBogus tests the creation of the ACT manifest end-to-end, with 100 bogus entries (i.e. 100 EC keys + default scenario = 3 nodes 1 unauthorized = 103 keys in the ACT manifest) // testACTWithBogus tests the creation of the ACT manifest end-to-end, with 100 bogus entries (i.e. 100 EC keys + default scenario = 3 nodes 1 unauthorized = 103 keys in the ACT manifest)
func testACTWithBogus(t *testing.T) { func testACTWithBogus(t *testing.T, cluster *testCluster) {
testACT(t, 100) testACT(t, cluster, 100)
} }
// testACT tests the e2e creation, uploading and downloading of an ACT access control with both EC keys AND password protection // testACT tests the e2e creation, uploading and downloading of an ACT access control with both EC keys AND password protection
@ -373,7 +376,7 @@ func testACTWithBogus(t *testing.T) {
// set and also protects the ACT with a password. the third node should fail decoding the reference as it will not be granted access. // set and also protects the ACT with a password. the third node should fail decoding the reference as it will not be granted access.
// the third node then then tries to download using a correct password (and succeeds) then uses a wrong password and fails. // the third node then then tries to download using a correct password (and succeeds) then uses a wrong password and fails.
// the publisher uploads through one of the nodes then disappears. // the publisher uploads through one of the nodes then disappears.
func testACT(t *testing.T, bogusEntries int) { func testACT(t *testing.T, cluster *testCluster, bogusEntries int) {
var uploadThroughNode = cluster.Nodes[0] var uploadThroughNode = cluster.Nodes[0]
client := swarmapi.NewClient(uploadThroughNode.URL) client := swarmapi.NewClient(uploadThroughNode.URL)

View file

@ -59,15 +59,6 @@ func init() {
const clusterSize = 3 const clusterSize = 3
var clusteronce sync.Once
var cluster *testCluster
func initCluster(t *testing.T) {
clusteronce.Do(func() {
cluster = newTestCluster(t, clusterSize)
})
}
func serverFunc(api *api.API) swarmhttp.TestServer { func serverFunc(api *api.API) swarmhttp.TestServer {
return swarmhttp.NewServer(api, "") return swarmhttp.NewServer(api, "")
} }
@ -165,10 +156,8 @@ outer:
} }
func (c *testCluster) Shutdown() { func (c *testCluster) Shutdown() {
for _, node := range c.Nodes { c.Stop()
node.Shutdown() c.Cleanup()
}
os.RemoveAll(c.TmpDir)
} }
func (c *testCluster) Stop() { func (c *testCluster) Stop() {
@ -179,16 +168,35 @@ func (c *testCluster) Stop() {
func (c *testCluster) StartNewNodes(t *testing.T, size int) { func (c *testCluster) StartNewNodes(t *testing.T, size int) {
c.Nodes = make([]*testNode, 0, size) c.Nodes = make([]*testNode, 0, size)
errors := make(chan error, size)
nodes := make(chan *testNode, size)
for i := 0; i < size; i++ { for i := 0; i < size; i++ {
dir := filepath.Join(c.TmpDir, fmt.Sprintf("swarm%02d", i)) go func(nodeIndex int) {
if err := os.Mkdir(dir, 0700); err != nil { dir := filepath.Join(c.TmpDir, fmt.Sprintf("swarm%02d", nodeIndex))
t.Fatal(err) if err := os.Mkdir(dir, 0700); err != nil {
errors <- err
return
}
node := newTestNode(t, dir)
node.Name = fmt.Sprintf("swarm%02d", nodeIndex)
nodes <- node
}(i)
}
for i := 0; i < size; i++ {
select {
case node := <-nodes:
c.Nodes = append(c.Nodes, node)
case err := <-errors:
t.Error(err)
} }
}
node := newTestNode(t, dir) if t.Failed() {
node.Name = fmt.Sprintf("swarm%02d", i) c.Shutdown()
t.FailNow()
c.Nodes = append(c.Nodes, node)
} }
} }

View file

@ -46,11 +46,12 @@ func TestSwarmUp(t *testing.T) {
t.Skip() t.Skip()
} }
initCluster(t) cluster := newTestCluster(t, clusterSize)
defer cluster.Shutdown()
cases := []struct { cases := []struct {
name string name string
f func(t *testing.T) f func(t *testing.T, cluster *testCluster)
}{ }{
{"NoEncryption", testNoEncryption}, {"NoEncryption", testNoEncryption},
{"Encrypted", testEncrypted}, {"Encrypted", testEncrypted},
@ -60,31 +61,33 @@ func TestSwarmUp(t *testing.T) {
} }
for _, tc := range cases { for _, tc := range cases {
t.Run(tc.name, tc.f) t.Run(tc.name, func(t *testing.T) {
tc.f(t, cluster)
})
} }
} }
// testNoEncryption tests that running 'swarm up' makes the resulting file // testNoEncryption tests that running 'swarm up' makes the resulting file
// available from all nodes via the HTTP API // available from all nodes via the HTTP API
func testNoEncryption(t *testing.T) { func testNoEncryption(t *testing.T, cluster *testCluster) {
testDefault(false, t) testDefault(t, cluster, false)
} }
// testEncrypted tests that running 'swarm up --encrypted' makes the resulting file // testEncrypted tests that running 'swarm up --encrypted' makes the resulting file
// available from all nodes via the HTTP API // available from all nodes via the HTTP API
func testEncrypted(t *testing.T) { func testEncrypted(t *testing.T, cluster *testCluster) {
testDefault(true, t) testDefault(t, cluster, true)
} }
func testRecursiveNoEncryption(t *testing.T) { func testRecursiveNoEncryption(t *testing.T, cluster *testCluster) {
testRecursive(false, t) testRecursive(t, cluster, false)
} }
func testRecursiveEncrypted(t *testing.T) { func testRecursiveEncrypted(t *testing.T, cluster *testCluster) {
testRecursive(true, t) testRecursive(t, cluster, true)
} }
func testDefault(toEncrypt bool, t *testing.T) { func testDefault(t *testing.T, cluster *testCluster, toEncrypt bool) {
tmpFileName := testutil.TempFileWithContent(t, data) tmpFileName := testutil.TempFileWithContent(t, data)
defer os.Remove(tmpFileName) defer os.Remove(tmpFileName)
@ -189,7 +192,7 @@ func testDefault(toEncrypt bool, t *testing.T) {
} }
} }
func testRecursive(toEncrypt bool, t *testing.T) { func testRecursive(t *testing.T, cluster *testCluster, toEncrypt bool) {
tmpUploadDir, err := ioutil.TempDir("", "swarm-test") tmpUploadDir, err := ioutil.TempDir("", "swarm-test")
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
@ -279,14 +282,14 @@ func testRecursive(toEncrypt bool, t *testing.T) {
// testDefaultPathAll tests swarm recursive upload with relative and absolute // testDefaultPathAll tests swarm recursive upload with relative and absolute
// default paths and with encryption. // default paths and with encryption.
func testDefaultPathAll(t *testing.T) { func testDefaultPathAll(t *testing.T, cluster *testCluster) {
testDefaultPath(false, false, t) testDefaultPath(t, cluster, false, false)
testDefaultPath(false, true, t) testDefaultPath(t, cluster, false, true)
testDefaultPath(true, false, t) testDefaultPath(t, cluster, true, false)
testDefaultPath(true, true, t) testDefaultPath(t, cluster, true, true)
} }
func testDefaultPath(toEncrypt bool, absDefaultPath bool, t *testing.T) { func testDefaultPath(t *testing.T, cluster *testCluster, toEncrypt bool, absDefaultPath bool) {
tmp, err := ioutil.TempDir("", "swarm-defaultpath-test") tmp, err := ioutil.TempDir("", "swarm-defaultpath-test")
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)

View file

@ -9,6 +9,7 @@ import (
"sync" "sync"
"github.com/ethereum/go-ethereum/metrics" "github.com/ethereum/go-ethereum/metrics"
"github.com/ethereum/go-ethereum/metrics/prometheus"
) )
type exp struct { type exp struct {
@ -42,6 +43,7 @@ func Exp(r metrics.Registry) {
// http.HandleFunc("/debug/vars", e.expHandler) // http.HandleFunc("/debug/vars", e.expHandler)
// haven't found an elegant way, so just use a different endpoint // haven't found an elegant way, so just use a different endpoint
http.Handle("/debug/metrics", h) http.Handle("/debug/metrics", h)
http.Handle("/debug/metrics/prometheus", prometheus.Handler(r))
} }
// ExpHandler will return an expvar powered metrics handler. // ExpHandler will return an expvar powered metrics handler.

View file

@ -0,0 +1,115 @@
// Copyright 2019 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 <http://www.gnu.org/licenses/>.
package prometheus
import (
"bytes"
"fmt"
"strconv"
"strings"
"github.com/ethereum/go-ethereum/metrics"
)
var (
typeGaugeTpl = "# TYPE %s gauge\n"
typeCounterTpl = "# TYPE %s counter\n"
typeSummaryTpl = "# TYPE %s summary\n"
keyValueTpl = "%s %v\n\n"
keyQuantileTagValueTpl = "%s {quantile=\"%s\"} %v\n\n"
)
// collector is a collection of byte buffers that aggregate Prometheus reports
// for different metric types.
type collector struct {
buff *bytes.Buffer
}
// newCollector createa a new Prometheus metric aggregator.
func newCollector() *collector {
return &collector{
buff: &bytes.Buffer{},
}
}
func (c *collector) addCounter(name string, m metrics.Counter) {
c.writeGaugeCounter(name, m.Count())
}
func (c *collector) addGauge(name string, m metrics.Gauge) {
c.writeGaugeCounter(name, m.Value())
}
func (c *collector) addGaugeFloat64(name string, m metrics.GaugeFloat64) {
c.writeGaugeCounter(name, m.Value())
}
func (c *collector) addHistogram(name string, m metrics.Histogram) {
pv := []float64{0.5, 0.75, 0.95, 0.99, 0.999, 0.9999}
ps := m.Percentiles(pv)
c.writeSummaryCounter(name, m.Count())
for i := range pv {
c.writeSummaryPercentile(name, strconv.FormatFloat(pv[i], 'f', -1, 64), ps[i])
}
}
func (c *collector) addMeter(name string, m metrics.Meter) {
c.writeGaugeCounter(name, m.Count())
}
func (c *collector) addTimer(name string, m metrics.Timer) {
pv := []float64{0.5, 0.75, 0.95, 0.99, 0.999, 0.9999}
ps := m.Percentiles(pv)
c.writeSummaryCounter(name, m.Count())
for i := range pv {
c.writeSummaryPercentile(name, strconv.FormatFloat(pv[i], 'f', -1, 64), ps[i])
}
}
func (c *collector) addResettingTimer(name string, m metrics.ResettingTimer) {
if len(m.Values()) <= 0 {
return
}
ps := m.Percentiles([]float64{50, 95, 99})
val := m.Values()
c.writeSummaryCounter(name, len(val))
c.writeSummaryPercentile(name, "0.50", ps[0])
c.writeSummaryPercentile(name, "0.95", ps[1])
c.writeSummaryPercentile(name, "0.99", ps[2])
}
func (c *collector) writeGaugeCounter(name string, value interface{}) {
name = mutateKey(name)
c.buff.WriteString(fmt.Sprintf(typeGaugeTpl, name))
c.buff.WriteString(fmt.Sprintf(keyValueTpl, name, value))
}
func (c *collector) writeSummaryCounter(name string, value interface{}) {
name = mutateKey(name + "_count")
c.buff.WriteString(fmt.Sprintf(typeCounterTpl, name))
c.buff.WriteString(fmt.Sprintf(keyValueTpl, name, value))
}
func (c *collector) writeSummaryPercentile(name, p string, value interface{}) {
name = mutateKey(name)
c.buff.WriteString(fmt.Sprintf(typeSummaryTpl, name))
c.buff.WriteString(fmt.Sprintf(keyQuantileTagValueTpl, name, p, value))
}
func mutateKey(key string) string {
return strings.Replace(key, "/", "_", -1)
}

View file

@ -0,0 +1,68 @@
// Copyright 2019 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 <http://www.gnu.org/licenses/>.
// Package prometheus exposes go-metrics into a Prometheus format.
package prometheus
import (
"fmt"
"net/http"
"sort"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/metrics"
)
// Handler returns an HTTP handler which dump metrics in Prometheus format.
func Handler(reg metrics.Registry) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
// Gather and pre-sort the metrics to avoid random listings
var names []string
reg.Each(func(name string, i interface{}) {
names = append(names, name)
})
sort.Strings(names)
// Aggregate all the metris into a Prometheus collector
c := newCollector()
for _, name := range names {
i := reg.Get(name)
switch m := i.(type) {
case metrics.Counter:
c.addCounter(name, m.Snapshot())
case metrics.Gauge:
c.addGauge(name, m.Snapshot())
case metrics.GaugeFloat64:
c.addGaugeFloat64(name, m.Snapshot())
case metrics.Histogram:
c.addHistogram(name, m.Snapshot())
case metrics.Meter:
c.addMeter(name, m.Snapshot())
case metrics.Timer:
c.addTimer(name, m.Snapshot())
case metrics.ResettingTimer:
c.addResettingTimer(name, m.Snapshot())
default:
log.Warn("Unknown Prometheus metric type", "type", fmt.Sprintf("%T", i))
}
}
w.Header().Add("Content-Type", "text/plain")
w.Header().Add("Content-Length", fmt.Sprint(c.buff.Len()))
w.Write(c.buff.Bytes())
})
}

View file

@ -18,6 +18,7 @@ package core
import ( import (
"bytes" "bytes"
"encoding/hex"
"encoding/json" "encoding/json"
"fmt" "fmt"
"io/ioutil" "io/ioutil"
@ -183,17 +184,13 @@ func NewAbiDBFromFile(path string) (*AbiDb, error) {
return db, nil return db, nil
} }
// NewAbiDBFromFiles loads both the standard signature database and a custom database. The latter will be used // NewAbiDBFromFiles loads both the standard signature database (resource file)and a custom database.
// to write new values into if they are submitted via the API // The latter will be used to write new values into if they are submitted via the API
func NewAbiDBFromFiles(standard, custom string) (*AbiDb, error) { func NewAbiDBFromFiles(raw []byte, custom string) (*AbiDb, error) {
db := &AbiDb{make(map[string]string), make(map[string]string), custom} db := &AbiDb{make(map[string]string), make(map[string]string), custom}
db.customdbPath = custom db.customdbPath = custom
raw, err := ioutil.ReadFile(standard)
if err != nil {
return nil, err
}
if err := json.Unmarshal(raw, &db.db); err != nil { if err := json.Unmarshal(raw, &db.db); err != nil {
return nil, err return nil, err
} }
@ -207,7 +204,6 @@ func NewAbiDBFromFiles(standard, custom string) (*AbiDb, error) {
return nil, err return nil, err
} }
} }
return db, nil return db, nil
} }
@ -217,7 +213,7 @@ func (db *AbiDb) LookupMethodSelector(id []byte) (string, error) {
if len(id) < 4 { if len(id) < 4 {
return "", fmt.Errorf("Expected 4-byte id, got %d", len(id)) return "", fmt.Errorf("Expected 4-byte id, got %d", len(id))
} }
sig := common.ToHex(id[:4]) sig := hex.EncodeToString(id[:4])
if key, exists := db.db[sig]; exists { if key, exists := db.db[sig]; exists {
return key, nil return key, nil
} }
@ -226,6 +222,7 @@ func (db *AbiDb) LookupMethodSelector(id []byte) (string, error) {
} }
return "", fmt.Errorf("Signature %v not found", sig) return "", fmt.Errorf("Signature %v not found", sig)
} }
func (db *AbiDb) Size() int { func (db *AbiDb) Size() int {
return len(db.db) return len(db.db)
} }
@ -255,6 +252,6 @@ func (db *AbiDb) AddSignature(selector string, data []byte) error {
if err == nil { if err == nil {
return nil return nil
} }
sig := common.ToHex(data[:4]) sig := hex.EncodeToString(data[:4])
return db.saveCustomAbi(selector, sig) return db.saveCustomAbi(selector, sig)
} }

View file

@ -205,7 +205,7 @@ func TestCustomABI(t *testing.T) {
t.Fatal(err) t.Fatal(err)
} }
filename := fmt.Sprintf("%s/4byte_custom.json", d) filename := fmt.Sprintf("%s/4byte_custom.json", d)
abidb, err := NewAbiDBFromFiles("../../cmd/clef/4byte.json", filename) abidb, err := NewAbiDBFromFiles([]byte(""), filename)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }

View file

@ -38,6 +38,7 @@ type Validator struct {
func NewValidator(db *AbiDb) *Validator { func NewValidator(db *AbiDb) *Validator {
return &Validator{db} return &Validator{db}
} }
func testSelector(selector string, data []byte) (*decodedCallData, error) { func testSelector(selector string, data []byte) (*decodedCallData, error) {
if selector == "" { if selector == "" {
return nil, fmt.Errorf("selector not found") return nil, fmt.Errorf("selector not found")

View file

@ -25,6 +25,8 @@ import (
"sort" "sort"
"testing" "testing"
"github.com/ethereum/go-ethereum/swarm/testutil"
"github.com/ethereum/go-ethereum/swarm/storage" "github.com/ethereum/go-ethereum/swarm/storage"
"github.com/ethereum/go-ethereum/swarm/storage/feed/lookup" "github.com/ethereum/go-ethereum/swarm/storage/feed/lookup"
@ -43,7 +45,13 @@ func serverFunc(api *api.API) swarmhttp.TestServer {
func TestClientUploadDownloadRaw(t *testing.T) { func TestClientUploadDownloadRaw(t *testing.T) {
testClientUploadDownloadRaw(false, t) testClientUploadDownloadRaw(false, t)
} }
func TestClientUploadDownloadRawEncrypted(t *testing.T) { func TestClientUploadDownloadRawEncrypted(t *testing.T) {
if testutil.RaceEnabled {
t.Skip("flaky with -race on Travis")
// See: https://github.com/ethersphere/go-ethereum/issues/1254
}
testClientUploadDownloadRaw(true, t) testClientUploadDownloadRaw(true, t)
} }

View file

@ -34,41 +34,41 @@ type TestServer interface {
} }
func NewTestSwarmServer(t *testing.T, serverFunc func(*api.API) TestServer, resolver api.Resolver) *TestSwarmServer { func NewTestSwarmServer(t *testing.T, serverFunc func(*api.API) TestServer, resolver api.Resolver) *TestSwarmServer {
dir, err := ioutil.TempDir("", "swarm-storage-test") swarmDir, err := ioutil.TempDir("", "swarm-storage-test")
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
localStore, err := localstore.New(dir, make([]byte, 32), nil) localStore, err := localstore.New(swarmDir, make([]byte, 32), nil)
if err != nil { if err != nil {
os.RemoveAll(dir) os.RemoveAll(swarmDir)
t.Fatal(err) t.Fatal(err)
} }
fileStore := storage.NewFileStore(localStore, storage.NewFileStoreParams()) fileStore := storage.NewFileStore(localStore, storage.NewFileStoreParams())
// Swarm feeds test setup // Swarm feeds test setup
feedsDir, err := ioutil.TempDir("", "swarm-feeds-test") feedsDir, err := ioutil.TempDir("", "swarm-feeds-test")
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
rhparams := &feed.HandlerParams{} feeds, err := feed.NewTestHandler(feedsDir, &feed.HandlerParams{})
rh, err := feed.NewTestHandler(feedsDir, rhparams)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
a := api.NewAPI(fileStore, resolver, rh.Handler, nil) swarmApi := api.NewAPI(fileStore, resolver, feeds.Handler, nil)
srv := httptest.NewServer(serverFunc(a)) apiServer := httptest.NewServer(serverFunc(swarmApi))
tss := &TestSwarmServer{ tss := &TestSwarmServer{
Server: srv, Server: apiServer,
FileStore: fileStore, FileStore: fileStore,
dir: dir, dir: swarmDir,
Hasher: storage.MakeHashFunc(storage.DefaultHash)(), Hasher: storage.MakeHashFunc(storage.DefaultHash)(),
cleanup: func() { cleanup: func() {
srv.Close() apiServer.Close()
rh.Close() fileStore.Close()
os.RemoveAll(dir) feeds.Close()
os.RemoveAll(swarmDir)
os.RemoveAll(feedsDir) os.RemoveAll(feedsDir)
}, },
CurrentTime: 42, CurrentTime: 42,