mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-17 09:23:48 +00:00
swarm/, cmd/swarm: Amend comments from @lmars PR 204
This commit is contained in:
parent
249e1a8aaa
commit
a16d0af41d
11 changed files with 166 additions and 217 deletions
|
|
@ -560,7 +560,7 @@ func registerBzzService(bzzconfig *bzzapi.Config, ctx *cli.Context, stack *node.
|
|||
}
|
||||
|
||||
// In production, mockStore must be always nil.
|
||||
return swarm.NewSwarm(ctx, swapClient, ensClient, bzzconfig, bzzconfig.SwapEnabled, bzzconfig.SyncEnabled, bzzconfig.Cors, bzzconfig.PssEnabled, bzzconfig.ResourceEnabled, nil)
|
||||
return swarm.NewSwarm(ctx, swapClient, ensClient, bzzconfig, nil)
|
||||
}
|
||||
//register within the ethereum node
|
||||
if err := stack.Register(boot); err != nil {
|
||||
|
|
|
|||
|
|
@ -23,7 +23,6 @@ import (
|
|||
"errors"
|
||||
"fmt"
|
||||
"math/big"
|
||||
"strconv"
|
||||
|
||||
"github.com/ethereum/go-ethereum"
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
|
|
@ -77,13 +76,19 @@ type rpcBlock struct {
|
|||
UncleHashes []common.Hash `json:"uncles"`
|
||||
}
|
||||
|
||||
func (ec *Client) BlockNumber(ctx context.Context) (uint64, error) {
|
||||
var number string
|
||||
err := ec.c.CallContext(ctx, &number, "eth_blockNumber")
|
||||
func (ec *Client) BlockNumber(ctx context.Context) (big.Int, error) {
|
||||
var numberstr string
|
||||
number := &big.Int{}
|
||||
err := ec.c.CallContext(ctx, &numberstr, "eth_blockNumber")
|
||||
if err != nil {
|
||||
return 0, err
|
||||
return *number, err
|
||||
}
|
||||
return strconv.ParseUint(number, 10, 64)
|
||||
var ok bool
|
||||
number, ok = number.SetString(numberstr, 10)
|
||||
if !ok {
|
||||
err = errors.New("Failed to parse bigint")
|
||||
}
|
||||
return *number, err
|
||||
}
|
||||
|
||||
func (ec *Client) getBlock(ctx context.Context, method string, args ...interface{}) (*types.Block, error) {
|
||||
|
|
|
|||
|
|
@ -365,13 +365,13 @@ func (self *Api) BuildDirectoryTree(mhash string, nameresolver bool) (key storag
|
|||
}
|
||||
|
||||
// Look up mutable resource updates at specific periods and versions
|
||||
func (self *Api) DbLookup(key storage.Key, name string, period uint32, version uint32) (storage.Key, io.ReadSeeker, int, error) {
|
||||
func (self *Api) DbLookup(key storage.Key, name string, period uint32, version uint32) (storage.Key, []byte, error) {
|
||||
var err error
|
||||
if version != 0 {
|
||||
if period == 0 {
|
||||
currentblocknumber, err := self.resource.GetBlock()
|
||||
if err != nil {
|
||||
return nil, nil, 0, fmt.Errorf("Could not determine latest block: %v", err)
|
||||
return nil, nil, fmt.Errorf("Could not determine latest block: %v", err)
|
||||
}
|
||||
period = self.resource.BlockToPeriod(name, currentblocknumber)
|
||||
}
|
||||
|
|
@ -382,13 +382,13 @@ func (self *Api) DbLookup(key storage.Key, name string, period uint32, version u
|
|||
_, err = self.resource.LookupLatestByName(name, true)
|
||||
}
|
||||
if err != nil {
|
||||
return nil, nil, 0, err
|
||||
return nil, nil, err
|
||||
}
|
||||
key, data, err := self.resource.GetContent(name)
|
||||
if err != nil {
|
||||
return nil, nil, 0, err
|
||||
return nil, nil, err
|
||||
}
|
||||
return key, bytes.NewReader(data), len(data), nil
|
||||
return key, data, nil
|
||||
}
|
||||
|
||||
func (self *Api) DbCreate(name string, frequency uint64) (err error) {
|
||||
|
|
|
|||
|
|
@ -110,8 +110,8 @@ func (self *Config) Init(prvKey *ecdsa.PrivateKey) {
|
|||
self.PublicKey = pubkeyhex
|
||||
self.BzzKey = keyhex
|
||||
|
||||
if self.SwapEnabled {
|
||||
self.Swap.Init(self.Contract, prvKey)
|
||||
//self.SyncParams.Init(self.Path)
|
||||
//self.HiveParams.Init(self.Path)
|
||||
}
|
||||
self.StoreParams.Init(self.Path)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -49,12 +49,9 @@ func TestConfig(t *testing.T) {
|
|||
if one.PublicKey == "" {
|
||||
t.Fatal("Expected PublicKey to be set")
|
||||
}
|
||||
|
||||
//the Init function should append subdirs to the given path
|
||||
if one.Swap.PayProfile.Beneficiary == (common.Address{}) {
|
||||
if one.Swap.PayProfile.Beneficiary == (common.Address{}) && one.SwapEnabled {
|
||||
t.Fatal("Failed to correctly initialize SwapParams")
|
||||
}
|
||||
|
||||
if one.StoreParams.ChunkDbPath == one.Path {
|
||||
t.Fatal("Failed to correctly initialize StoreParams")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -295,13 +295,12 @@ func (s *Server) HandlePostDb(w http.ResponseWriter, r *Request) {
|
|||
if r.ContentLength == 0 {
|
||||
frequency, err := strconv.ParseUint(r.uri.Path, 10, 64)
|
||||
if err != nil {
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
http.ServeContent(w, &r.Request, "", time.Now(), bytes.NewReader([]byte(err.Error())))
|
||||
s.BadRequest(w, r, fmt.Sprintf("Cannot parse frequency parameter: %v", err))
|
||||
return
|
||||
}
|
||||
err = s.api.DbCreate(r.uri.Addr, frequency)
|
||||
if err != nil {
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
s.Error(w, r, fmt.Errorf("Resource creation failed: %v", err))
|
||||
return
|
||||
}
|
||||
} else {
|
||||
|
|
@ -324,8 +323,8 @@ func (s *Server) HandlePostDb(w http.ResponseWriter, r *Request) {
|
|||
// bzz-db[-[immutable|-raw]]://<id> - get latest update
|
||||
// bzz-db[-[immutable|-raw]]://<id>/<n> - get latest update on period n
|
||||
// bzz-db[-[immutable|-raw]]://<id>/<n>/<m> - get update version m of period n
|
||||
// <id> = ens name or hash
|
||||
func (s *Server) HandleGetDb(w http.ResponseWriter, r *Request) {
|
||||
w.Header().Set("Content-Type", "application/octet-stream")
|
||||
|
||||
rootKey, err := s.api.Resolve(r.uri)
|
||||
if err != nil {
|
||||
|
|
@ -340,34 +339,39 @@ func (s *Server) HandleGetDb(w http.ResponseWriter, r *Request) {
|
|||
var updateKey storage.Key
|
||||
var period uint64
|
||||
var version uint64
|
||||
var data io.ReadSeeker
|
||||
var data []byte
|
||||
var dataLength int
|
||||
now := time.Now()
|
||||
switch len(params) {
|
||||
case 0:
|
||||
updateKey, data, dataLength, err = s.api.DbLookup(rootKey, r.uri.Addr, 0, 0)
|
||||
break
|
||||
updateKey, data, err = s.api.DbLookup(rootKey, r.uri.Addr, 0, 0)
|
||||
case 2:
|
||||
version, err = strconv.ParseUint(params[1], 10, 32)
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
updateKey, data, err = s.api.DbLookup(rootKey, r.uri.Addr, uint32(period), uint32(version))
|
||||
case 1:
|
||||
version, err = strconv.ParseUint(params[1], 10, 32)
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
period, err = strconv.ParseUint(params[0], 10, 32)
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
updateKey, data, dataLength, err = s.api.DbLookup(rootKey, r.uri.Addr, uint32(period), uint32(version))
|
||||
break
|
||||
updateKey, data, err = s.api.DbLookup(rootKey, r.uri.Addr, uint32(period), uint32(version))
|
||||
default:
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
err = fmt.Errorf("params 0-2")
|
||||
s.BadRequest(w, r, fmt.Sprintf("Invalid mutable resource request"))
|
||||
return
|
||||
}
|
||||
if err != nil {
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
s.Error(w, r, fmt.Errorf("Mutable resource lookup failed: %v", err))
|
||||
return
|
||||
}
|
||||
if !r.uri.DbRaw() {
|
||||
w.Header().Set("Content-Type", "application/octet-stream")
|
||||
} else {
|
||||
entry := api.ManifestEntry{
|
||||
Hash: rootKey.Hex(),
|
||||
Path: updateKey.Hex(),
|
||||
|
|
@ -376,9 +380,9 @@ func (s *Server) HandleGetDb(w http.ResponseWriter, r *Request) {
|
|||
ModTime: now,
|
||||
Status: http.StatusOK,
|
||||
}
|
||||
mode := (6 << 2) | (4 << 1) | 4
|
||||
mode := 0644
|
||||
if s.api.DbIsValidated() {
|
||||
mode |= 2 << 1
|
||||
mode |= (2 << 3) | 2
|
||||
}
|
||||
entry.Mode = int64(mode)
|
||||
manifest := api.Manifest{
|
||||
|
|
@ -388,12 +392,13 @@ func (s *Server) HandleGetDb(w http.ResponseWriter, r *Request) {
|
|||
}
|
||||
manifestJson, err := json.Marshal(manifest)
|
||||
if err != nil {
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
s.Error(w, r, fmt.Errorf("Could not convert manifest to json: %v", err))
|
||||
return
|
||||
}
|
||||
data = bytes.NewReader(manifestJson)
|
||||
w.Header().Set("Content-Type", api.DbManifestType)
|
||||
data = []byte(manifestJson)
|
||||
}
|
||||
http.ServeContent(w, &r.Request, "", now, data)
|
||||
http.ServeContent(w, &r.Request, "", now, bytes.NewReader(data))
|
||||
}
|
||||
|
||||
// HandleGet handles a GET request to
|
||||
|
|
|
|||
|
|
@ -47,46 +47,53 @@ func TestBzzGetDb(t *testing.T) {
|
|||
keybytes := make([]byte, common.HashLength) // nearest we get to source of info
|
||||
_, err := rand.Read(keybytes)
|
||||
if err != nil {
|
||||
fmt.Printf("err: %v\n", err)
|
||||
return
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
url := fmt.Sprintf("%s/bzz-db:/%s/42", srv.URL, fmt.Sprintf("%x", keybytes))
|
||||
resp, err := http.Post(url, "application/octet-stream", nil)
|
||||
if err != nil {
|
||||
fmt.Printf("err: %v\n", err)
|
||||
return
|
||||
t.Fatal(err)
|
||||
}
|
||||
b, err := ioutil.ReadAll(resp.Body)
|
||||
fmt.Printf("Create: %s : %s\n", resp.Status, b)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
log.Debug("Create", "status", resp.Status, "body", b)
|
||||
|
||||
url = fmt.Sprintf("%s/bzz-db:/%s", srv.URL, fmt.Sprintf("%x", keybytes))
|
||||
url = fmt.Sprintf("%s/bzz-db:/%x", srv.URL, keybytes)
|
||||
data := []byte("foo")
|
||||
resp, err = http.Post(url, "application/octet-stream", bytes.NewReader(data))
|
||||
if err != nil {
|
||||
fmt.Printf("err: %v\n", err)
|
||||
return
|
||||
t.Fatal(err)
|
||||
}
|
||||
b, err = ioutil.ReadAll(resp.Body)
|
||||
fmt.Printf("Update: %s : %s\n", resp.Status, b)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
log.Debug("Update", "status", resp.Status, "body", b)
|
||||
|
||||
url = fmt.Sprintf("%s/bzz-db-raw:/%s", srv.URL, fmt.Sprintf("%x", keybytes))
|
||||
resp, err = http.Get(url)
|
||||
if err != nil {
|
||||
fmt.Printf("err: %v\n", err)
|
||||
return
|
||||
t.Fatal(err)
|
||||
}
|
||||
b, err = ioutil.ReadAll(resp.Body)
|
||||
fmt.Printf("Get: %s : %s\n", resp.Status, b)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
log.Debug("Get raw", "status", resp.Status, "body", b)
|
||||
|
||||
url = fmt.Sprintf("%s/bzz-db:/%s", srv.URL, fmt.Sprintf("%x", keybytes))
|
||||
resp, err = http.Get(url)
|
||||
if err != nil {
|
||||
fmt.Printf("err: %v\n", err)
|
||||
return
|
||||
t.Fatal(err)
|
||||
}
|
||||
b, err = ioutil.ReadAll(resp.Body)
|
||||
fmt.Printf("Get: %s : %s\n", resp.Status, b)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
log.Debug("Get manifest", "status", resp.Status, "body", b)
|
||||
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import (
|
|||
"context"
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"math/big"
|
||||
"path/filepath"
|
||||
"sync"
|
||||
"time"
|
||||
|
|
@ -12,7 +13,6 @@ import (
|
|||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/crypto"
|
||||
"github.com/ethereum/go-ethereum/ethclient"
|
||||
"github.com/ethereum/go-ethereum/log"
|
||||
)
|
||||
|
||||
|
|
@ -58,6 +58,10 @@ type ResourceValidator interface {
|
|||
sign(common.Hash) (Signature, error) // SignFunc
|
||||
}
|
||||
|
||||
type ethApi interface {
|
||||
BlockNumber(context.Context) (big.Int, error)
|
||||
}
|
||||
|
||||
// Mutable resource is an entity which allows updates to a resource
|
||||
// without resorting to ENS on each update.
|
||||
// The update scheme is built on swarm chunks with chunk keys following
|
||||
|
|
@ -119,8 +123,10 @@ type ResourceValidator interface {
|
|||
// TODO: Include modtime in chunk data + signature
|
||||
type ResourceHandler struct {
|
||||
ChunkStore
|
||||
ctx context.Context
|
||||
cancelFunc func()
|
||||
validator ResourceValidator
|
||||
ethClient *ethclient.Client
|
||||
ethClient ethApi
|
||||
resources map[string]*resource
|
||||
hashLock sync.Mutex
|
||||
resourceLock sync.RWMutex
|
||||
|
|
@ -134,7 +140,7 @@ type ResourceHandler struct {
|
|||
// Create or open resource update chunk store
|
||||
//
|
||||
// If validator is nil, signature and access validation will be deactivated
|
||||
func NewResourceHandler(datadir string, cloudStore CloudStore, ethClient *ethclient.Client, validator ResourceValidator) (*ResourceHandler, error) {
|
||||
func NewResourceHandler(datadir string, cloudStore CloudStore, ethClient ethApi, validator ResourceValidator) (*ResourceHandler, error) {
|
||||
|
||||
hashfunc := MakeHashFunc(SHA3Hash)
|
||||
|
||||
|
|
@ -602,17 +608,11 @@ func (self *ResourceHandler) Close() {
|
|||
}
|
||||
|
||||
func (self *ResourceHandler) GetBlock() (uint64, error) {
|
||||
return self.ethClient.BlockNumber(self.ctx)
|
||||
// get the block height and convert to uint64
|
||||
// var currentblock string
|
||||
// err := self.rpcClient.Call(¤tblock, "eth_blockNumber")
|
||||
// if err != nil {
|
||||
// return 0, err
|
||||
// }
|
||||
// if currentblock == "0x0" {
|
||||
// return 0, nil
|
||||
// }
|
||||
// return strconv.ParseUint(currentblock, 10, 64)
|
||||
bigblocknumber, err := self.ethClient.BlockNumber(self.ctx)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return bigblocknumber.Uint64(), nil
|
||||
}
|
||||
|
||||
// Calculate the period index (aka major version number) from a given block number
|
||||
|
|
@ -776,10 +776,7 @@ func isSafeName(name string) bool {
|
|||
if err != nil {
|
||||
return false
|
||||
}
|
||||
if validname != name {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
return validname == name
|
||||
}
|
||||
|
||||
// convenience for creating signature hashes of update data
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ package storage
|
|||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"crypto/ecdsa"
|
||||
"crypto/rand"
|
||||
"encoding/binary"
|
||||
|
|
@ -9,8 +10,6 @@ import (
|
|||
"io/ioutil"
|
||||
"math/big"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
|
@ -22,9 +21,7 @@ import (
|
|||
"github.com/ethereum/go-ethereum/contracts/ens/contract"
|
||||
"github.com/ethereum/go-ethereum/core"
|
||||
"github.com/ethereum/go-ethereum/crypto"
|
||||
"github.com/ethereum/go-ethereum/ethclient"
|
||||
"github.com/ethereum/go-ethereum/log"
|
||||
"github.com/ethereum/go-ethereum/rpc"
|
||||
)
|
||||
|
||||
var (
|
||||
|
|
@ -50,7 +47,7 @@ func init() {
|
|||
// so we use this wrapper to fake returning the block count
|
||||
type fakeBackend struct {
|
||||
*backends.SimulatedBackend
|
||||
blocknumber uint64
|
||||
blocknumber int64
|
||||
}
|
||||
|
||||
func (f *fakeBackend) Commit() {
|
||||
|
|
@ -60,13 +57,10 @@ func (f *fakeBackend) Commit() {
|
|||
f.blocknumber++
|
||||
}
|
||||
|
||||
// for faking the rpc service, since we don't need the whole node stack
|
||||
type FakeRPC struct {
|
||||
backend *fakeBackend
|
||||
}
|
||||
|
||||
func (r *FakeRPC) BlockNumber() (string, error) {
|
||||
return strconv.FormatUint(r.backend.blocknumber, 10), nil
|
||||
func (f *fakeBackend) BlockNumber(context context.Context) (big.Int, error) {
|
||||
f.blocknumber++
|
||||
biggie := big.NewInt(f.blocknumber)
|
||||
return *biggie, nil
|
||||
}
|
||||
|
||||
// check that signature address matches update signer address
|
||||
|
|
@ -84,8 +78,9 @@ func TestResourceReverse(t *testing.T) {
|
|||
// set up rpc and create resourcehandler
|
||||
rh, _, _, teardownTest, err := setupTest(nil, newTestValidator(signer.signContent))
|
||||
if err != nil {
|
||||
teardownTest(t, err)
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer teardownTest()
|
||||
|
||||
// generate a hash for block 4200 version 1
|
||||
key := rh.resourceHash(period, version, rh.nameHash(safeName))
|
||||
|
|
@ -94,14 +89,14 @@ func TestResourceReverse(t *testing.T) {
|
|||
data := make([]byte, 8)
|
||||
_, err = rand.Read(data)
|
||||
if err != nil {
|
||||
teardownTest(t, err)
|
||||
t.Fatal(err)
|
||||
}
|
||||
testHasher.Reset()
|
||||
testHasher.Write(data)
|
||||
digest := rh.keyDataHash(key, data)
|
||||
sig, err := rh.validator.sign(digest)
|
||||
if err != nil {
|
||||
teardownTest(t, err)
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
chunk := newUpdateChunk(key, &sig, period, version, safeName, data)
|
||||
|
|
@ -111,31 +106,30 @@ func TestResourceReverse(t *testing.T) {
|
|||
checkdigest := rh.keyDataHash(chunk.Key, checkdata)
|
||||
recoveredaddress, err := getAddressFromDataSig(checkdigest, *checksig)
|
||||
if err != nil {
|
||||
teardownTest(t, fmt.Errorf("Retrieve address from signature fail: %v", err))
|
||||
t.Fatalf("Retrieve address from signature fail: %v", err)
|
||||
}
|
||||
originaladdress := crypto.PubkeyToAddress(signer.privKey.PublicKey)
|
||||
|
||||
// check that the metadata retrieved from the chunk matches what we gave it
|
||||
if recoveredaddress != originaladdress {
|
||||
teardownTest(t, fmt.Errorf("addresses dont match: %x != %x", originaladdress, recoveredaddress))
|
||||
t.Fatalf("addresses dont match: %x != %x", originaladdress, recoveredaddress)
|
||||
}
|
||||
|
||||
if !bytes.Equal(key[:], chunk.Key[:]) {
|
||||
teardownTest(t, fmt.Errorf("Expected chunk key '%x', was '%x'", key, chunk.Key))
|
||||
t.Fatalf("Expected chunk key '%x', was '%x'", key, chunk.Key)
|
||||
}
|
||||
if period != checkperiod {
|
||||
teardownTest(t, fmt.Errorf("Expected period '%d', was '%d'", period, checkperiod))
|
||||
t.Fatalf("Expected period '%d', was '%d'", period, checkperiod)
|
||||
}
|
||||
if version != checkversion {
|
||||
teardownTest(t, fmt.Errorf("Expected version '%d', was '%d'", version, checkversion))
|
||||
t.Fatalf("Expected version '%d', was '%d'", version, checkversion)
|
||||
}
|
||||
if safeName != checkname {
|
||||
teardownTest(t, fmt.Errorf("Expected name '%s', was '%s'", safeName, checkname))
|
||||
t.Fatalf("Expected name '%s', was '%s'", safeName, checkname)
|
||||
}
|
||||
if !bytes.Equal(data, checkdata) {
|
||||
teardownTest(t, fmt.Errorf("Expectedn data '%x', was '%x'", data, checkdata))
|
||||
t.Fatalf("Expectedn data '%x', was '%x'", data, checkdata)
|
||||
}
|
||||
teardownTest(t, nil)
|
||||
}
|
||||
|
||||
// make updates and retrieve them based on periods and versions
|
||||
|
|
@ -143,34 +137,35 @@ func TestResourceHandler(t *testing.T) {
|
|||
|
||||
// make fake backend, set up rpc and create resourcehandler
|
||||
backend := &fakeBackend{
|
||||
blocknumber: startBlock,
|
||||
blocknumber: int64(startBlock),
|
||||
}
|
||||
rh, datadir, _, teardownTest, err := setupTest(backend, nil)
|
||||
if err != nil {
|
||||
teardownTest(t, err)
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer teardownTest()
|
||||
|
||||
// create a new resource
|
||||
_, err = rh.NewResource(safeName, resourceFrequency)
|
||||
if err != nil {
|
||||
teardownTest(t, err)
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// check that the new resource is stored correctly
|
||||
namehash := rh.nameHash(safeName)
|
||||
chunk, err := rh.ChunkStore.(*resourceChunkStore).localStore.(*LocalStore).memStore.Get(Key(namehash[:]))
|
||||
if err != nil {
|
||||
teardownTest(t, err)
|
||||
t.Fatal(err)
|
||||
} else if len(chunk.SData) < 16 {
|
||||
teardownTest(t, fmt.Errorf("chunk data must be minimum 16 bytes, is %d", len(chunk.SData)))
|
||||
t.Fatalf("chunk data must be minimum 16 bytes, is %d", len(chunk.SData))
|
||||
}
|
||||
startblocknumber := binary.LittleEndian.Uint64(chunk.SData[:8])
|
||||
chunkfrequency := binary.LittleEndian.Uint64(chunk.SData[8:])
|
||||
if startblocknumber != backend.blocknumber {
|
||||
teardownTest(t, fmt.Errorf("stored block number %d does not match provided block number %d", startblocknumber, backend.blocknumber))
|
||||
if startblocknumber != uint64(backend.blocknumber) {
|
||||
t.Fatalf("stored block number %d does not match provided block number %d", startblocknumber, backend.blocknumber)
|
||||
}
|
||||
if chunkfrequency != resourceFrequency {
|
||||
teardownTest(t, fmt.Errorf("stored frequency %d does not match provided frequency %d", chunkfrequency, resourceFrequency))
|
||||
t.Fatalf("stored frequency %d does not match provided frequency %d", chunkfrequency, resourceFrequency)
|
||||
}
|
||||
|
||||
// update halfway to first period
|
||||
|
|
@ -179,7 +174,7 @@ func TestResourceHandler(t *testing.T) {
|
|||
data := []byte("blinky")
|
||||
resourcekey["blinky"], err = rh.Update(safeName, data)
|
||||
if err != nil {
|
||||
teardownTest(t, err)
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// update on first period
|
||||
|
|
@ -187,7 +182,7 @@ func TestResourceHandler(t *testing.T) {
|
|||
data = []byte("pinky")
|
||||
resourcekey["pinky"], err = rh.Update(safeName, data)
|
||||
if err != nil {
|
||||
teardownTest(t, err)
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// update on second period
|
||||
|
|
@ -195,7 +190,7 @@ func TestResourceHandler(t *testing.T) {
|
|||
data = []byte("inky")
|
||||
resourcekey["inky"], err = rh.Update(safeName, data)
|
||||
if err != nil {
|
||||
teardownTest(t, err)
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// update just after second period
|
||||
|
|
@ -203,7 +198,7 @@ func TestResourceHandler(t *testing.T) {
|
|||
data = []byte("clyde")
|
||||
resourcekey["clyde"], err = rh.Update(safeName, data)
|
||||
if err != nil {
|
||||
teardownTest(t, err)
|
||||
t.Fatal(err)
|
||||
}
|
||||
time.Sleep(time.Second)
|
||||
rh.Close()
|
||||
|
|
@ -215,43 +210,42 @@ func TestResourceHandler(t *testing.T) {
|
|||
rh2, err := NewResourceHandler(datadir, &testCloudStore{}, rh.ethClient, nil)
|
||||
_, err = rh2.LookupLatestByName(safeName, true)
|
||||
if err != nil {
|
||||
teardownTest(t, err)
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// last update should be "clyde", version two, blockheight startblocknumber + (resourcefrequency * 3)
|
||||
if !bytes.Equal(rh2.resources[safeName].data, []byte("clyde")) {
|
||||
teardownTest(t, fmt.Errorf("resource data was %v, expected %v", rh2.resources[safeName].data, []byte("clyde")))
|
||||
t.Fatalf("resource data was %v, expected %v", rh2.resources[safeName].data, []byte("clyde"))
|
||||
}
|
||||
if rh2.resources[safeName].version != 2 {
|
||||
teardownTest(t, fmt.Errorf("resource version was %d, expected 2", rh2.resources[safeName].version))
|
||||
t.Fatalf("resource version was %d, expected 2", rh2.resources[safeName].version)
|
||||
}
|
||||
if rh2.resources[safeName].lastPeriod != 3 {
|
||||
teardownTest(t, fmt.Errorf("resource period was %d, expected 3", rh2.resources[safeName].lastPeriod))
|
||||
t.Fatalf("resource period was %d, expected 3", rh2.resources[safeName].lastPeriod)
|
||||
}
|
||||
log.Debug("Latest lookup", "period", rh2.resources[safeName].lastPeriod, "version", rh2.resources[safeName].version, "data", rh2.resources[safeName].data)
|
||||
|
||||
// specific block, latest version
|
||||
rsrc, err := rh2.LookupHistoricalByName(safeName, 3, true)
|
||||
if err != nil {
|
||||
teardownTest(t, err)
|
||||
t.Fatal(err)
|
||||
}
|
||||
// check data
|
||||
if !bytes.Equal(rsrc.data, []byte("clyde")) {
|
||||
teardownTest(t, fmt.Errorf("resource data (historical) was %v, expected %v", rh2.resources[domainName].data, []byte("clyde")))
|
||||
t.Fatalf("resource data (historical) was %v, expected %v", rh2.resources[domainName].data, []byte("clyde"))
|
||||
}
|
||||
log.Debug("Historical lookup", "period", rh2.resources[safeName].lastPeriod, "version", rh2.resources[safeName].version, "data", rh2.resources[safeName].data)
|
||||
|
||||
// specific block, specific version
|
||||
rsrc, err = rh2.LookupVersionByName(safeName, 3, 1, true)
|
||||
if err != nil {
|
||||
teardownTest(t, err)
|
||||
t.Fatal(err)
|
||||
}
|
||||
// check data
|
||||
if !bytes.Equal(rsrc.data, []byte("inky")) {
|
||||
teardownTest(t, fmt.Errorf("resource data (historical) was %v, expected %v", rh2.resources[domainName].data, []byte("inky")))
|
||||
t.Fatalf("resource data (historical) was %v, expected %v", rh2.resources[domainName].data, []byte("inky"))
|
||||
}
|
||||
log.Debug("Specific version lookup", "period", rh2.resources[safeName].lastPeriod, "version", rh2.resources[safeName].version, "data", rh2.resources[safeName].data)
|
||||
teardownTest(t, nil)
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -283,34 +277,33 @@ func TestResourceENSOwner(t *testing.T) {
|
|||
// set up rpc and create resourcehandler with ENS sim backend
|
||||
rh, _, _, teardownTest, err := setupTest(contractbackend, validator)
|
||||
if err != nil {
|
||||
teardownTest(t, err)
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer teardownTest()
|
||||
|
||||
// create new resource when we are owner = ok
|
||||
_, err = rh.NewResource(safeName, resourceFrequency)
|
||||
if err != nil {
|
||||
teardownTest(t, fmt.Errorf("Create resource fail: %v", err))
|
||||
t.Fatalf("Create resource fail: %v", err)
|
||||
}
|
||||
|
||||
data := []byte("foo")
|
||||
// update resource when we are owner = ok
|
||||
_, err = rh.Update(safeName, data)
|
||||
if err != nil {
|
||||
teardownTest(t, fmt.Errorf("Update resource fail: %v", err))
|
||||
t.Fatalf("Update resource fail: %v", err)
|
||||
}
|
||||
|
||||
// update resource when we are owner = ok
|
||||
signertwo, err := newTestSigner()
|
||||
if err != nil {
|
||||
teardownTest(t, err)
|
||||
t.Fatal(err)
|
||||
}
|
||||
rh.validator.(*ENSValidator).signFunc = signertwo.signContent
|
||||
_, err = rh.Update(safeName, data)
|
||||
if err == nil {
|
||||
teardownTest(t, fmt.Errorf("Expected resource update fail due to owner mismatch"))
|
||||
t.Fatalf("Expected resource update fail due to owner mismatch")
|
||||
}
|
||||
|
||||
teardownTest(t, nil)
|
||||
}
|
||||
|
||||
// fast-forward blockheight
|
||||
|
|
@ -321,7 +314,7 @@ func fwdBlocks(count int, backend *fakeBackend) {
|
|||
}
|
||||
|
||||
// create rpc and resourcehandler
|
||||
func setupTest(contractbackend bind.ContractBackend, validator ResourceValidator) (rh *ResourceHandler, datadir string, signer *testSigner, teardown func(*testing.T, error), err error) {
|
||||
func setupTest(backend ethApi, validator ResourceValidator) (rh *ResourceHandler, datadir string, signer *testSigner, teardown func(), err error) {
|
||||
|
||||
var fsClean func()
|
||||
var rpcClean func()
|
||||
|
|
@ -337,55 +330,18 @@ func setupTest(contractbackend bind.ContractBackend, validator ResourceValidator
|
|||
// temp datadir
|
||||
datadir, err = ioutil.TempDir("", "rh")
|
||||
if err != nil {
|
||||
return
|
||||
return nil, "", nil, nil, err
|
||||
}
|
||||
fsClean = func() {
|
||||
os.RemoveAll(datadir)
|
||||
}
|
||||
|
||||
// starting the whole stack just to get blocknumbers is too cumbersome
|
||||
// so we fake the rpc server to get blocknumbers for testing
|
||||
ipcpath := filepath.Join(datadir, "test.ipc")
|
||||
ipcl, err := rpc.CreateIPCListener(ipcpath)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
rpcserver := rpc.NewServer()
|
||||
var fake *fakeBackend
|
||||
if contractbackend != nil {
|
||||
fake = contractbackend.(*fakeBackend)
|
||||
}
|
||||
rpcserver.RegisterName("eth", &FakeRPC{
|
||||
backend: fake,
|
||||
})
|
||||
go func() {
|
||||
rpcserver.ServeListener(ipcl)
|
||||
}()
|
||||
rpcClean = func() {
|
||||
rpcserver.Stop()
|
||||
}
|
||||
|
||||
// connect to fake rpc
|
||||
rpcClient, err := rpc.Dial(ipcpath)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
ethClient := ethclient.NewClient(rpcClient)
|
||||
|
||||
rh, err = NewResourceHandler(datadir, &testCloudStore{}, ethClient, validator)
|
||||
teardown = func(t *testing.T, err error) {
|
||||
cleanF()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
rh, err = NewResourceHandler(datadir, &testCloudStore{}, backend, validator)
|
||||
return rh, datadir, signer, cleanF, nil
|
||||
}
|
||||
|
||||
// Set up simulated ENS backend for use with ENSResourceHandler tests
|
||||
func setupENS(addr common.Address, transactOpts *bind.TransactOpts, sub string, top string) (common.Address, bind.ContractBackend, error) {
|
||||
func setupENS(addr common.Address, transactOpts *bind.TransactOpts, sub string, top string) (common.Address, *fakeBackend, error) {
|
||||
|
||||
// create the domain hash values to pass to the ENS contract methods
|
||||
var tophash [32]byte
|
||||
|
|
|
|||
|
|
@ -58,8 +58,6 @@ type Swarm struct {
|
|||
bzz *network.Bzz // the logistic manager
|
||||
backend chequebook.Backend // simple blockchain Backend
|
||||
privateKey *ecdsa.PrivateKey
|
||||
corsString string
|
||||
swapEnabled bool
|
||||
lstore *storage.LocalStore // local store, needs to store for releasing resources after node stopped
|
||||
sfs *fuse.SwarmFS // need this to cleanup all the active mounts on node exit
|
||||
ps *pss.Pss
|
||||
|
|
@ -83,7 +81,7 @@ func (self *Swarm) API() *SwarmAPI {
|
|||
// implements node.Service
|
||||
// If mockStore is not nil, it will be used as the storage for chunk data.
|
||||
// MockStore should be used only for testing.
|
||||
func NewSwarm(ctx *node.ServiceContext, backend chequebook.Backend, ensClient *ethclient.Client, config *api.Config, swapEnabled, syncEnabled bool, cors string, pssEnabled bool, resourceEnabled bool, mockStore *mock.NodeStore) (self *Swarm, err error) {
|
||||
func NewSwarm(ctx *node.ServiceContext, backend chequebook.Backend, ensClient *ethclient.Client, config *api.Config, mockStore *mock.NodeStore) (self *Swarm, err error) {
|
||||
|
||||
if bytes.Equal(common.FromHex(config.PublicKey), storage.ZeroKey) {
|
||||
return nil, fmt.Errorf("empty public key")
|
||||
|
|
@ -94,10 +92,8 @@ func NewSwarm(ctx *node.ServiceContext, backend chequebook.Backend, ensClient *e
|
|||
|
||||
self = &Swarm{
|
||||
config: config,
|
||||
swapEnabled: swapEnabled,
|
||||
backend: backend,
|
||||
privateKey: config.Swap.PrivateKey(),
|
||||
corsString: cors,
|
||||
}
|
||||
log.Debug(fmt.Sprintf("Setting up Swarm service components"))
|
||||
|
||||
|
|
@ -139,7 +135,7 @@ func NewSwarm(ctx *node.ServiceContext, backend chequebook.Backend, ensClient *e
|
|||
log.Debug(fmt.Sprintf("-> Content Store API"))
|
||||
|
||||
// Pss = postal service over swarm (devp2p over bzz)
|
||||
if pssEnabled {
|
||||
if self.config.PssEnabled {
|
||||
pssparams := pss.NewPssParams(self.privateKey)
|
||||
self.ps = pss.NewPss(to, self.dpa, pssparams)
|
||||
if pss.IsActiveHandshake {
|
||||
|
|
@ -162,7 +158,7 @@ func NewSwarm(ctx *node.ServiceContext, backend chequebook.Backend, ensClient *e
|
|||
|
||||
var resourceHandler *storage.ResourceHandler
|
||||
// if use resource updates
|
||||
if resourceEnabled {
|
||||
if self.config.ResourceEnabled {
|
||||
var resourceValidator storage.ResourceValidator
|
||||
if self.dns != nil {
|
||||
resourceValidator, err = storage.NewENSValidator(config.EnsRoot, ensClient, transactOpts, storage.NewGenericResourceSigner(self.privateKey))
|
||||
|
|
@ -204,7 +200,7 @@ func (self *Swarm) Start(srv *p2p.Server) error {
|
|||
log.Warn("Updated bzz local addr", "oaddr", fmt.Sprintf("%x", newaddr.OAddr), "uaddr", fmt.Sprintf("%x", newaddr.UAddr))
|
||||
|
||||
// set chequebook
|
||||
if self.swapEnabled {
|
||||
if self.config.SwapEnabled {
|
||||
ctx := context.Background() // The initial setup has no deadline.
|
||||
err := self.SetChequebook(ctx)
|
||||
if err != nil {
|
||||
|
|
@ -237,14 +233,14 @@ func (self *Swarm) Start(srv *p2p.Server) error {
|
|||
addr := net.JoinHostPort(self.config.ListenAddr, self.config.Port)
|
||||
go httpapi.StartHttpServer(self.api, &httpapi.ServerConfig{
|
||||
Addr: addr,
|
||||
CorsString: self.corsString,
|
||||
CorsString: self.config.Cors,
|
||||
})
|
||||
}
|
||||
|
||||
log.Debug(fmt.Sprintf("Swarm http proxy started on port: %v", self.config.Port))
|
||||
|
||||
if self.corsString != "" {
|
||||
log.Debug(fmt.Sprintf("Swarm http proxy started with corsdomain: %v", self.corsString))
|
||||
if self.config.Cors != "" {
|
||||
log.Debug(fmt.Sprintf("Swarm http proxy started with corsdomain: %v", self.config.Cors))
|
||||
}
|
||||
|
||||
return nil
|
||||
|
|
|
|||
|
|
@ -17,21 +17,29 @@
|
|||
package testutil
|
||||
|
||||
import (
|
||||
"crypto/ecdsa"
|
||||
"context"
|
||||
"io/ioutil"
|
||||
"math/big"
|
||||
"net/http/httptest"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"testing"
|
||||
|
||||
"github.com/ethereum/go-ethereum/ethclient"
|
||||
"github.com/ethereum/go-ethereum/rpc"
|
||||
"github.com/ethereum/go-ethereum/swarm/api"
|
||||
httpapi "github.com/ethereum/go-ethereum/swarm/api/http"
|
||||
"github.com/ethereum/go-ethereum/swarm/storage"
|
||||
)
|
||||
|
||||
type fakeBackend struct {
|
||||
blocknumber int64
|
||||
}
|
||||
|
||||
func (f *fakeBackend) BlockNumber(ctx context.Context) (big.Int, error) {
|
||||
f.blocknumber++
|
||||
biggie := big.NewInt(f.blocknumber)
|
||||
return *biggie, nil
|
||||
}
|
||||
|
||||
func NewTestSwarmServer(t *testing.T) *TestSwarmServer {
|
||||
dir, err := ioutil.TempDir("", "swarm-storage-test")
|
||||
if err != nil {
|
||||
|
|
@ -60,28 +68,8 @@ func NewTestSwarmServer(t *testing.T) *TestSwarmServer {
|
|||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
ipcPath := filepath.Join(resourceDir, "test.ipc")
|
||||
ipcl, err := rpc.CreateIPCListener(ipcPath)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
rpcServer := rpc.NewServer()
|
||||
rpcServer.RegisterName("eth", &FakeRPC{})
|
||||
go func() {
|
||||
rpcServer.ServeListener(ipcl)
|
||||
}()
|
||||
rpcClean := func() {
|
||||
rpcServer.Stop()
|
||||
}
|
||||
|
||||
// connect to fake rpc
|
||||
rpcClient, err := rpc.Dial(ipcPath)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
ethClient := ethclient.NewClient(rpcClient)
|
||||
|
||||
rh, err := storage.NewResourceHandler(resourceDir, &testCloudStore{}, ethClient, nil)
|
||||
rh, err := storage.NewResourceHandler(resourceDir, &testCloudStore{}, &fakeBackend{}, nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
|
@ -94,8 +82,9 @@ func NewTestSwarmServer(t *testing.T) *TestSwarmServer {
|
|||
dir: dir,
|
||||
hasher: storage.MakeHashFunc(storage.SHA3Hash)(),
|
||||
cleanup: func() {
|
||||
srv.Close()
|
||||
rh.Close()
|
||||
rpcClean()
|
||||
dpa.Stop()
|
||||
os.RemoveAll(dir)
|
||||
os.RemoveAll(resourceDir)
|
||||
},
|
||||
|
|
@ -105,16 +94,13 @@ func NewTestSwarmServer(t *testing.T) *TestSwarmServer {
|
|||
type TestSwarmServer struct {
|
||||
*httptest.Server
|
||||
hasher storage.SwarmHash
|
||||
privatekey *ecdsa.PrivateKey
|
||||
Dpa *storage.DPA
|
||||
dir string
|
||||
cleanup func()
|
||||
}
|
||||
|
||||
func (t *TestSwarmServer) Close() {
|
||||
t.Server.Close()
|
||||
t.Dpa.Stop()
|
||||
os.RemoveAll(t.dir)
|
||||
t.cleanup()
|
||||
}
|
||||
|
||||
type testCloudStore struct {
|
||||
|
|
|
|||
Loading…
Reference in a new issue