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