mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-17 09:23:48 +00:00
swarm/storage: Change validator, subclassing -> member
This commit is contained in:
parent
c45ce79937
commit
52e529e04b
3 changed files with 112 additions and 119 deletions
|
|
@ -91,15 +91,15 @@ type resource struct {
|
|||
// stored using a separate store, and forwarding/syncing protocols carry per-chunk
|
||||
// flags to tell whether the chunk can be validated or not; if not it is to be
|
||||
// treated as a resource update chunk.
|
||||
type ResourceHandler interface {
|
||||
ChunkStore
|
||||
NewResource(name string, frequency uint64) (*resource, error)
|
||||
Update(name string, data []byte) (Key, error)
|
||||
resourceHash(namehash common.Hash, period uint32, version uint32) Key
|
||||
|
||||
type ResourceValidator interface {
|
||||
isOwner(string) (bool, error)
|
||||
nameHash(string) common.Hash
|
||||
}
|
||||
|
||||
type RawResourceHandler struct {
|
||||
type ResourceHandler struct {
|
||||
ChunkStore
|
||||
validator ResourceValidator
|
||||
rpcClient *rpc.Client
|
||||
resources map[string]*resource
|
||||
hashLock sync.Mutex
|
||||
|
|
@ -107,11 +107,10 @@ type RawResourceHandler struct {
|
|||
hasher SwarmHash
|
||||
privKey *ecdsa.PrivateKey
|
||||
maxChunkData int64
|
||||
nameHashFunc func(string) common.Hash
|
||||
}
|
||||
|
||||
// Create or open resource update chunk store
|
||||
func NewRawResourceHandler(privKey *ecdsa.PrivateKey, datadir string, cloudStore CloudStore, rpcClient *rpc.Client, nameHashFunc func(string) common.Hash) (*RawResourceHandler, error) {
|
||||
func NewResourceHandler(privKey *ecdsa.PrivateKey, datadir string, cloudStore CloudStore, rpcClient *rpc.Client, validator ResourceValidator) (*ResourceHandler, error) {
|
||||
path := filepath.Join(datadir, "resource")
|
||||
dbStore, err := NewDbStore(datadir, nil, singletonSwarmDbCapacity, 0)
|
||||
if err != nil {
|
||||
|
|
@ -123,7 +122,7 @@ func NewRawResourceHandler(privKey *ecdsa.PrivateKey, datadir string, cloudStore
|
|||
}
|
||||
hasher := MakeHashFunc("SHA3")
|
||||
|
||||
rh := &RawResourceHandler{
|
||||
rh := &ResourceHandler{
|
||||
ChunkStore: newResourceChunkStore(path, hasher, localStore, cloudStore),
|
||||
rpcClient: rpcClient,
|
||||
resources: make(map[string]*resource),
|
||||
|
|
@ -132,14 +131,16 @@ func NewRawResourceHandler(privKey *ecdsa.PrivateKey, datadir string, cloudStore
|
|||
maxChunkData: DefaultBranches * int64(hasher().Size()),
|
||||
}
|
||||
|
||||
if nameHashFunc == nil {
|
||||
rh.nameHashFunc = func(name string) common.Hash {
|
||||
if validator != nil {
|
||||
rh.validator = validator
|
||||
} else {
|
||||
rh.validator = NewGenericValidator(func(name string) common.Hash {
|
||||
rh.hashLock.Lock()
|
||||
defer rh.hashLock.Unlock()
|
||||
rh.hasher.Reset()
|
||||
rh.hasher.Write([]byte(name))
|
||||
return common.BytesToHash(rh.hasher.Sum(nil))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
return rh, nil
|
||||
|
|
@ -186,14 +187,21 @@ func NewResource(name string, startBlock uint64, frequency uint64, nameHashFunc
|
|||
// Creates a new root entry for a mutable resource identified by `name` with the specified `frequency`.
|
||||
//
|
||||
// The start block of the resource update will be the actual current block height of the connected network.
|
||||
func (self *RawResourceHandler) NewResource(name string, frequency uint64) (*resource, error) {
|
||||
func (self *ResourceHandler) NewResource(name string, frequency uint64) (*resource, error) {
|
||||
|
||||
ok, err := self.validator.isOwner(name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
} else if !ok {
|
||||
return nil, fmt.Errorf("Not owner of '%s'", name)
|
||||
}
|
||||
|
||||
validname, err := validateInput(name, frequency)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
nameHash := self.nameHashFunc(validname)
|
||||
nameHash := self.validator.nameHash(validname)
|
||||
|
||||
// get our blockheight at this time
|
||||
currentblock, err := self.getBlock()
|
||||
|
|
@ -236,7 +244,7 @@ func (self *RawResourceHandler) NewResource(name string, frequency uint64) (*res
|
|||
//
|
||||
// Method will fail if resource is already registered in this session, unless
|
||||
// `allowOverwrite` is set
|
||||
func (self *RawResourceHandler) SetExternalResource(rsrc *resource, allowOverwrite bool) error {
|
||||
func (self *ResourceHandler) SetExternalResource(rsrc *resource, allowOverwrite bool) error {
|
||||
|
||||
utfname, err := idna.ToUnicode(rsrc.name)
|
||||
if err != nil {
|
||||
|
|
@ -273,7 +281,7 @@ func (self *RawResourceHandler) SetExternalResource(rsrc *resource, allowOverwri
|
|||
// root chunk.
|
||||
// It is the callers responsibility to make sure that this chunk exists (if the resource
|
||||
// update root data was retrieved externally, it typically doesn't)
|
||||
func (self *RawResourceHandler) LookupVersion(name string, period uint32, version uint32, refresh bool) (*resource, error) {
|
||||
func (self *ResourceHandler) LookupVersion(name string, period uint32, version uint32, refresh bool) (*resource, error) {
|
||||
rsrc, err := self.loadResource(name, refresh)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
|
@ -289,7 +297,7 @@ func (self *RawResourceHandler) LookupVersion(name string, period uint32, versio
|
|||
// and returned.
|
||||
//
|
||||
// See also (*ResourceHandler).LookupVersion
|
||||
func (self *RawResourceHandler) LookupHistorical(name string, period uint32, refresh bool) (*resource, error) {
|
||||
func (self *ResourceHandler) LookupHistorical(name string, period uint32, refresh bool) (*resource, error) {
|
||||
rsrc, err := self.loadResource(name, refresh)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
|
@ -307,7 +315,7 @@ func (self *RawResourceHandler) LookupHistorical(name string, period uint32, ref
|
|||
// Version iteration is done as in (*ResourceHandler).LookupHistorical
|
||||
//
|
||||
// See also (*ResourceHandler).LookupHistorical
|
||||
func (self *RawResourceHandler) LookupLatest(name string, refresh bool) (*resource, error) {
|
||||
func (self *ResourceHandler) LookupLatest(name string, refresh bool) (*resource, error) {
|
||||
|
||||
// get our blockheight at this time and the next block of the update period
|
||||
rsrc, err := self.loadResource(name, refresh)
|
||||
|
|
@ -323,7 +331,7 @@ func (self *RawResourceHandler) LookupLatest(name string, refresh bool) (*resour
|
|||
}
|
||||
|
||||
// base code for public lookup methods
|
||||
func (self *RawResourceHandler) lookup(rsrc *resource, name string, period uint32, version uint32, refresh bool) (*resource, error) {
|
||||
func (self *ResourceHandler) lookup(rsrc *resource, name string, period uint32, version uint32, refresh bool) (*resource, error) {
|
||||
|
||||
if period == 0 {
|
||||
return nil, fmt.Errorf("period must be >0")
|
||||
|
|
@ -366,7 +374,7 @@ func (self *RawResourceHandler) lookup(rsrc *resource, name string, period uint3
|
|||
}
|
||||
|
||||
// load existing mutable resource into resource struct
|
||||
func (self *RawResourceHandler) loadResource(name string, refresh bool) (*resource, error) {
|
||||
func (self *ResourceHandler) loadResource(name string, refresh bool) (*resource, error) {
|
||||
// if the resource is not known to this session we must load it
|
||||
// if refresh is set, we force load
|
||||
|
||||
|
|
@ -379,7 +387,7 @@ func (self *RawResourceHandler) loadResource(name string, refresh bool) (*resour
|
|||
return nil, err
|
||||
}
|
||||
rsrc.name = validname
|
||||
rsrc.nameHash = self.nameHashFunc(validname)
|
||||
rsrc.nameHash = self.validator.nameHash(validname)
|
||||
|
||||
// get the root info chunk and update the cached value
|
||||
chunk, err := self.Get(Key(rsrc.nameHash[:]))
|
||||
|
|
@ -409,7 +417,7 @@ func (self *RawResourceHandler) loadResource(name string, refresh bool) (*resour
|
|||
}
|
||||
|
||||
// update mutable resource index map with specified content
|
||||
func (self *RawResourceHandler) updateResourceIndex(rsrc *resource, chunk *Chunk, indexname *string) (*resource, error) {
|
||||
func (self *ResourceHandler) updateResourceIndex(rsrc *resource, chunk *Chunk, indexname *string) (*resource, error) {
|
||||
|
||||
// rsrc update data chunks are total hacks
|
||||
// and have no size prefix :D
|
||||
|
|
@ -455,7 +463,14 @@ func parseUpdate(blob []byte) (period uint32, version uint32, ensname []byte, da
|
|||
// It is the caller's responsibility to make sure that this data is not stale.
|
||||
//
|
||||
// A resource update cannot span chunks, and thus has max length 4096
|
||||
func (self *RawResourceHandler) Update(name string, data []byte) (Key, error) {
|
||||
func (self *ResourceHandler) Update(name string, data []byte) (Key, error) {
|
||||
|
||||
ok, err := self.validator.isOwner(name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
} else if !ok {
|
||||
return nil, fmt.Errorf("Not owner of '%s'", name)
|
||||
}
|
||||
|
||||
// can be only one chunk long minus 65 byte signature
|
||||
if int64(len(data)) > self.maxChunkData {
|
||||
|
|
@ -527,11 +542,11 @@ func (self *RawResourceHandler) Update(name string, data []byte) (Key, error) {
|
|||
|
||||
// Closes the datastore.
|
||||
// Always call this at shutdown to avoid data corruption.
|
||||
func (self *RawResourceHandler) Close() {
|
||||
func (self *ResourceHandler) Close() {
|
||||
self.ChunkStore.Close()
|
||||
}
|
||||
|
||||
func (self *RawResourceHandler) getBlock() (uint64, error) {
|
||||
func (self *ResourceHandler) getBlock() (uint64, error) {
|
||||
// get the block height and convert to uint64
|
||||
var currentblock string
|
||||
err := self.rpcClient.Call(¤tblock, "eth_blockNumber")
|
||||
|
|
@ -544,28 +559,28 @@ func (self *RawResourceHandler) getBlock() (uint64, error) {
|
|||
return strconv.ParseUint(currentblock, 10, 64)
|
||||
}
|
||||
|
||||
func (self *RawResourceHandler) BlockToPeriod(name string, blocknumber uint64) uint32 {
|
||||
func (self *ResourceHandler) BlockToPeriod(name string, blocknumber uint64) uint32 {
|
||||
return getNextPeriod(self.resources[name].startBlock, blocknumber, self.resources[name].frequency)
|
||||
}
|
||||
|
||||
func (self *RawResourceHandler) PeriodToBlock(name string, period uint32) uint64 {
|
||||
func (self *ResourceHandler) PeriodToBlock(name string, period uint32) uint64 {
|
||||
return self.resources[name].startBlock + (uint64(period) * self.resources[name].frequency)
|
||||
}
|
||||
|
||||
func (self *RawResourceHandler) getResource(name string) *resource {
|
||||
func (self *ResourceHandler) getResource(name string) *resource {
|
||||
self.resourceLock.RLock()
|
||||
defer self.resourceLock.RUnlock()
|
||||
rsrc := self.resources[name]
|
||||
return rsrc
|
||||
}
|
||||
|
||||
func (self *RawResourceHandler) setResource(name string, rsrc *resource) {
|
||||
func (self *ResourceHandler) setResource(name string, rsrc *resource) {
|
||||
self.resourceLock.Lock()
|
||||
defer self.resourceLock.Unlock()
|
||||
self.resources[name] = rsrc
|
||||
}
|
||||
|
||||
func (self *RawResourceHandler) resourceHash(namehash common.Hash, period uint32, version uint32) Key {
|
||||
func (self *ResourceHandler) resourceHash(namehash common.Hash, period uint32, version uint32) Key {
|
||||
// format is: hash(namehash|period|version)
|
||||
self.hashLock.Lock()
|
||||
defer self.hashLock.Unlock()
|
||||
|
|
@ -579,7 +594,7 @@ func (self *RawResourceHandler) resourceHash(namehash common.Hash, period uint32
|
|||
return self.hasher.Sum(nil)
|
||||
}
|
||||
|
||||
func (self *RawResourceHandler) signContent(data []byte) ([]byte, error) {
|
||||
func (self *ResourceHandler) signContent(data []byte) ([]byte, error) {
|
||||
self.hashLock.Lock()
|
||||
self.hasher.Reset()
|
||||
self.hasher.Write(data)
|
||||
|
|
@ -596,7 +611,7 @@ func (self *RawResourceHandler) signContent(data []byte) ([]byte, error) {
|
|||
return datawithsign, nil
|
||||
}
|
||||
|
||||
func (self *RawResourceHandler) getContentAccount(chunkdata []byte) (common.Address, error) {
|
||||
func (self *ResourceHandler) getContentAccount(chunkdata []byte) (common.Address, error) {
|
||||
if len(chunkdata) <= signatureLength {
|
||||
return common.Address{}, fmt.Errorf("zero-length data")
|
||||
}
|
||||
|
|
@ -612,7 +627,7 @@ func (self *RawResourceHandler) getContentAccount(chunkdata []byte) (common.Addr
|
|||
return crypto.PubkeyToAddress(*pub), nil
|
||||
}
|
||||
|
||||
func (self *RawResourceHandler) verifyContent(chunkdata []byte) error {
|
||||
func (self *ResourceHandler) verifyContent(chunkdata []byte) error {
|
||||
address, err := self.getContentAccount(chunkdata)
|
||||
if err != nil {
|
||||
return err
|
||||
|
|
@ -621,7 +636,7 @@ func (self *RawResourceHandler) verifyContent(chunkdata []byte) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (self *RawResourceHandler) hasUpdate(name string, period uint32) bool {
|
||||
func (self *ResourceHandler) hasUpdate(name string, period uint32) bool {
|
||||
if self.resources[name].lastPeriod == period {
|
||||
return true
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,74 +1,54 @@
|
|||
package storage
|
||||
|
||||
import (
|
||||
"crypto/ecdsa"
|
||||
"fmt"
|
||||
|
||||
"github.com/ethereum/go-ethereum/accounts/abi/bind"
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/contracts/ens"
|
||||
"github.com/ethereum/go-ethereum/crypto"
|
||||
"github.com/ethereum/go-ethereum/rpc"
|
||||
)
|
||||
|
||||
// Implements Mutable Resources as offchain ENS resolvers
|
||||
//
|
||||
// The data part of the update is forced to be a valid ENS content hash
|
||||
//
|
||||
// Also, the ENSResourceHandler only allows creation and update of
|
||||
// Resources from the ENS owner's address
|
||||
//
|
||||
type ENSResourceHandler struct {
|
||||
*RawResourceHandler
|
||||
addr common.Address
|
||||
ensapi *ens.ENS
|
||||
// ENS validation of mutable resource owners
|
||||
type ENSValidator struct {
|
||||
owner common.Address
|
||||
api *ens.ENS
|
||||
}
|
||||
|
||||
func NewENSResourceHandler(privKey *ecdsa.PrivateKey, datadir string, cloudStore CloudStore, rpcClient *rpc.Client, backend bind.ContractBackend, ensAddr common.Address) (*ENSResourceHandler, error) {
|
||||
transactOpts := bind.NewKeyedTransactor(privKey)
|
||||
ensinstance, err := ens.NewENS(transactOpts, ensAddr, backend)
|
||||
func NewENSValidator(owneraddress common.Address, contractaddress common.Address, backend bind.ContractBackend, transactOpts *bind.TransactOpts) (*ENSValidator, error) {
|
||||
var err error
|
||||
validator := &ENSValidator{}
|
||||
validator.api, err = ens.NewENS(transactOpts, contractaddress, backend)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
rh, err := NewRawResourceHandler(privKey, datadir, cloudStore, rpcClient, ens.EnsNode)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
validator.owner = owneraddress
|
||||
return validator, nil
|
||||
}
|
||||
rh.nameHashFunc = func(name string) common.Hash {
|
||||
|
||||
func (self *ENSValidator) isOwner(name string) (bool, error) {
|
||||
owneraddr, err := self.api.Owner(self.nameHash(name))
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
return owneraddr == self.owner, nil
|
||||
}
|
||||
|
||||
func (self *ENSValidator) nameHash(name string) common.Hash {
|
||||
return ens.EnsNode(name)
|
||||
}
|
||||
|
||||
return &ENSResourceHandler{
|
||||
RawResourceHandler: rh,
|
||||
addr: crypto.PubkeyToAddress(privKey.PublicKey),
|
||||
ensapi: ensinstance,
|
||||
}, nil
|
||||
// Default fallthrough validation of mutable resource ownership
|
||||
type GenericValidator struct {
|
||||
hashFunc func(string) common.Hash
|
||||
}
|
||||
|
||||
func (self *ENSResourceHandler) NewResource(name string, frequency uint64) (*resource, error) {
|
||||
ok, err := self.IsOwner(name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
} else if !ok {
|
||||
return nil, fmt.Errorf("Not Owner")
|
||||
func NewGenericValidator(hashFunc func(string) common.Hash) *GenericValidator {
|
||||
return &GenericValidator{
|
||||
hashFunc: hashFunc,
|
||||
}
|
||||
return self.RawResourceHandler.NewResource(name, frequency)
|
||||
}
|
||||
func (self *GenericValidator) isOwner(name string) (bool, error) {
|
||||
return true, nil
|
||||
}
|
||||
|
||||
func (self *ENSResourceHandler) Update(name string, data []byte) (Key, error) {
|
||||
ok, err := self.IsOwner(name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
} else if !ok {
|
||||
return nil, fmt.Errorf("Not Owner")
|
||||
}
|
||||
return self.RawResourceHandler.Update(name, data)
|
||||
}
|
||||
|
||||
func (self *ENSResourceHandler) IsOwner(name string) (bool, error) {
|
||||
owneraddr, err := self.ensapi.Owner(self.RawResourceHandler.nameHashFunc(name))
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("ENS error: %v", err)
|
||||
}
|
||||
return owneraddr == self.addr, nil
|
||||
func (self *GenericValidator) nameHash(name string) common.Hash {
|
||||
return self.hashFunc(name)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -74,7 +74,7 @@ func TestResourceSignature(t *testing.T) {
|
|||
}
|
||||
|
||||
// set up rpc and create resourcehandler
|
||||
rh, _, err, teardownTest := setupTest(privkey, nil, zeroAddr)
|
||||
rh, _, err, teardownTest := setupTest(privkey, nil, nil)
|
||||
if err != nil {
|
||||
teardownTest(t, err)
|
||||
}
|
||||
|
|
@ -110,8 +110,7 @@ func TestResourceSignature(t *testing.T) {
|
|||
|
||||
// check that we can recover the owner account from the update chunk's signature
|
||||
// TODO: change this to verifyContent on ENS integration
|
||||
rawrh := rh.(*RawResourceHandler)
|
||||
recoveredaddress, err := rawrh.getContentAccount(chunk.SData)
|
||||
recoveredaddress, err := rh.getContentAccount(chunk.SData)
|
||||
if err != nil {
|
||||
teardownTest(t, err)
|
||||
}
|
||||
|
|
@ -136,7 +135,7 @@ func TestResourceReverseLookup(t *testing.T) {
|
|||
backend := &fakeBackend{
|
||||
blocknumber: startBlock,
|
||||
}
|
||||
rh, _, err, teardownTest := setupTest(privkey, backend, zeroAddr)
|
||||
rh, _, err, teardownTest := setupTest(privkey, backend, nil)
|
||||
if err != nil {
|
||||
teardownTest(t, err)
|
||||
}
|
||||
|
|
@ -154,8 +153,7 @@ func TestResourceReverseLookup(t *testing.T) {
|
|||
if err != nil {
|
||||
teardownTest(t, err)
|
||||
}
|
||||
rawrh := rh.(*RawResourceHandler)
|
||||
chunk, err := rawrh.ChunkStore.(*resourceChunkStore).localStore.(*LocalStore).memStore.Get(Key(resourcekey))
|
||||
chunk, err := rh.ChunkStore.(*resourceChunkStore).localStore.(*LocalStore).memStore.Get(Key(resourcekey))
|
||||
if err != nil {
|
||||
teardownTest(t, err)
|
||||
}
|
||||
|
|
@ -197,7 +195,7 @@ func TestResourceHandler(t *testing.T) {
|
|||
backend := &fakeBackend{
|
||||
blocknumber: startBlock,
|
||||
}
|
||||
rh, datadir, err, teardownTest := setupTest(privkey, backend, zeroAddr)
|
||||
rh, datadir, err, teardownTest := setupTest(privkey, backend, nil)
|
||||
if err != nil {
|
||||
teardownTest(t, err)
|
||||
}
|
||||
|
|
@ -213,9 +211,8 @@ func TestResourceHandler(t *testing.T) {
|
|||
}
|
||||
|
||||
// check that the new resource is stored correctly
|
||||
rawrh := rh.(*RawResourceHandler)
|
||||
namehash := rawrh.nameHashFunc(resourcevalidname)
|
||||
chunk, err := rawrh.ChunkStore.(*resourceChunkStore).localStore.(*LocalStore).memStore.Get(Key(namehash[:]))
|
||||
namehash := rh.validator.nameHash(resourcevalidname)
|
||||
chunk, err := rh.ChunkStore.(*resourceChunkStore).localStore.(*LocalStore).memStore.Get(Key(namehash[:]))
|
||||
if err != nil {
|
||||
teardownTest(t, err)
|
||||
} else if len(chunk.SData) < 16 {
|
||||
|
|
@ -265,7 +262,7 @@ func TestResourceHandler(t *testing.T) {
|
|||
// it will match on second iteration startblocknumber + (resourceFrequency * 3)
|
||||
fwdBlocks(int(resourceFrequency*2)-1, backend)
|
||||
|
||||
rh2, err := NewRawResourceHandler(privkey, datadir, &testCloudStore{}, rawrh.rpcClient, nil)
|
||||
rh2, err := NewResourceHandler(privkey, datadir, &testCloudStore{}, rh.rpcClient, nil)
|
||||
_, err = rh2.LookupLatest(domainName, true)
|
||||
if err != nil {
|
||||
teardownTest(t, err)
|
||||
|
|
@ -282,7 +279,7 @@ func TestResourceHandler(t *testing.T) {
|
|||
teardownTest(t, fmt.Errorf("resource period was %d, expected 3", rh2.resources[domainName].lastPeriod))
|
||||
}
|
||||
|
||||
rsrc, err := NewResource(domainName, startblocknumber, resourceFrequency, rh2.nameHashFunc)
|
||||
rsrc, err := NewResource(domainName, startblocknumber, resourceFrequency, rh2.validator.nameHash)
|
||||
if err != nil {
|
||||
teardownTest(t, err)
|
||||
}
|
||||
|
|
@ -342,15 +339,24 @@ func TestResourceENSOwner(t *testing.T) {
|
|||
return
|
||||
}
|
||||
|
||||
// ens address and transact options
|
||||
addr := crypto.PubkeyToAddress(privkey.PublicKey)
|
||||
transactOpts := bind.NewKeyedTransactor(privkey)
|
||||
|
||||
// set up ENS sim
|
||||
domainparts := strings.Split(domainName, ".")
|
||||
addr, contractbackend, err := setupENS(privkey, domainparts[0], domainparts[1])
|
||||
contractAddr, contractbackend, err := setupENS(addr, transactOpts, domainparts[0], domainparts[1])
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
validator, err := NewENSValidator(addr, contractAddr, contractbackend, transactOpts)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// set up rpc and create resourcehandler with ENS sim backend
|
||||
rh, _, err, teardownTest := setupTest(privkey, contractbackend, addr)
|
||||
rh, _, err, teardownTest := setupTest(privkey, contractbackend, validator)
|
||||
if err != nil {
|
||||
teardownTest(t, err)
|
||||
}
|
||||
|
|
@ -358,20 +364,20 @@ func TestResourceENSOwner(t *testing.T) {
|
|||
// create new resource when we are owner = ok
|
||||
_, err = rh.NewResource(domainName, 42)
|
||||
if err != nil {
|
||||
teardownTest(t, err)
|
||||
teardownTest(t, fmt.Errorf("Create resource fail: %v", err))
|
||||
}
|
||||
|
||||
// update resource when we are owner = ok
|
||||
_, err = rh.Update(domainName, []byte("foo"))
|
||||
if err != nil {
|
||||
teardownTest(t, err)
|
||||
teardownTest(t, fmt.Errorf("Update resource fail: %v", err))
|
||||
}
|
||||
|
||||
// create new resource when we are NOT owner = !ok
|
||||
rawrh := rh.(*ENSResourceHandler)
|
||||
rawrh.privKey = privkeytwo
|
||||
rawrh.addr = crypto.PubkeyToAddress(privkeytwo.PublicKey)
|
||||
_, err = rawrh.NewResource(domainName, 42)
|
||||
addrtwo := crypto.PubkeyToAddress(privkeytwo.PublicKey)
|
||||
validator.owner = addrtwo
|
||||
|
||||
_, err = rh.NewResource(domainName, 42)
|
||||
if err == nil {
|
||||
teardownTest(t, fmt.Errorf("Expected resource create fail due to owner mismatch"))
|
||||
}
|
||||
|
|
@ -392,7 +398,7 @@ func fwdBlocks(count int, backend *fakeBackend) {
|
|||
}
|
||||
|
||||
// create rpc and resourcehandler
|
||||
func setupTest(privkey *ecdsa.PrivateKey, contractbackend bind.ContractBackend, ensaddr common.Address) (rh ResourceHandler, datadir string, err error, teardown func(*testing.T, error)) {
|
||||
func setupTest(privkey *ecdsa.PrivateKey, contractbackend bind.ContractBackend, validator ResourceValidator) (rh *ResourceHandler, datadir string, err error, teardown func(*testing.T, error)) {
|
||||
|
||||
var fsClean func()
|
||||
var rpcClean func()
|
||||
|
|
@ -443,11 +449,7 @@ func setupTest(privkey *ecdsa.PrivateKey, contractbackend bind.ContractBackend,
|
|||
}
|
||||
|
||||
// choose if with ens or not
|
||||
if ensaddr != zeroAddr {
|
||||
rh, err = NewENSResourceHandler(privkey, datadir, &testCloudStore{}, rpcclient, contractbackend, ensaddr)
|
||||
} else {
|
||||
rh, err = NewRawResourceHandler(privkey, datadir, &testCloudStore{}, rpcclient, nil)
|
||||
}
|
||||
rh, err = NewResourceHandler(privkey, datadir, &testCloudStore{}, rpcclient, validator)
|
||||
teardown = func(t *testing.T, err error) {
|
||||
cleanF()
|
||||
if err != nil {
|
||||
|
|
@ -459,7 +461,7 @@ func setupTest(privkey *ecdsa.PrivateKey, contractbackend bind.ContractBackend,
|
|||
}
|
||||
|
||||
// Set up simulated ENS backend for use with ENSResourceHandler tests
|
||||
func setupENS(privkey *ecdsa.PrivateKey, sub string, top string) (common.Address, bind.ContractBackend, error) {
|
||||
func setupENS(addr common.Address, transactOpts *bind.TransactOpts, sub string, top string) (common.Address, bind.ContractBackend, error) {
|
||||
|
||||
// create the domain hash values to pass to the ENS contract methods
|
||||
var tophash [32]byte
|
||||
|
|
@ -472,16 +474,12 @@ func setupENS(privkey *ecdsa.PrivateKey, sub string, top string) (common.Address
|
|||
hasher.Write([]byte(sub))
|
||||
copy(subhash[:], hasher.Sum(nil))
|
||||
|
||||
// private key -> address is owner of domain
|
||||
addr := crypto.PubkeyToAddress(privkey.PublicKey)
|
||||
|
||||
// initialize contract backend and deploy
|
||||
transactOpts := bind.NewKeyedTransactor(privkey)
|
||||
contractBackend := &fakeBackend{
|
||||
SimulatedBackend: backends.NewSimulatedBackend(core.GenesisAlloc{addr: {Balance: big.NewInt(1000000000)}}),
|
||||
}
|
||||
|
||||
ensAddr, _, ensinstance, err := contract.DeployENS(transactOpts, contractBackend)
|
||||
contractAddress, _, ensinstance, err := contract.DeployENS(transactOpts, contractBackend)
|
||||
if err != nil {
|
||||
return zeroAddr, nil, fmt.Errorf("can't deploy: %v", err)
|
||||
}
|
||||
|
|
@ -502,7 +500,7 @@ func setupENS(privkey *ecdsa.PrivateKey, sub string, top string) (common.Address
|
|||
}
|
||||
contractBackend.Commit()
|
||||
|
||||
return ensAddr, contractBackend, nil
|
||||
return contractAddress, contractBackend, nil
|
||||
}
|
||||
|
||||
type testCloudStore struct {
|
||||
|
|
|
|||
Loading…
Reference in a new issue