mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-17 09:23:48 +00:00
swarm/storage: Add proper backend + wrapper for simulated testbackend
This commit is contained in:
parent
3ec6a51ca6
commit
b635d7fdc1
2 changed files with 101 additions and 53 deletions
|
|
@ -11,9 +11,11 @@ import (
|
||||||
|
|
||||||
"golang.org/x/net/idna"
|
"golang.org/x/net/idna"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/accounts/abi/bind"
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/contracts/ens"
|
"github.com/ethereum/go-ethereum/contracts/ens"
|
||||||
"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"
|
"github.com/ethereum/go-ethereum/rpc"
|
||||||
)
|
)
|
||||||
|
|
@ -99,7 +101,9 @@ type resource struct {
|
||||||
// TODO: signature validation
|
// TODO: signature validation
|
||||||
type ResourceHandler struct {
|
type ResourceHandler struct {
|
||||||
ChunkStore
|
ChunkStore
|
||||||
ethapi *rpc.Client
|
ethapi *ethclient.Client
|
||||||
|
rpcClient *rpc.Client
|
||||||
|
ensapi *ens.ENS
|
||||||
resources map[string]*resource
|
resources map[string]*resource
|
||||||
hashLock sync.Mutex
|
hashLock sync.Mutex
|
||||||
resourceLock sync.RWMutex
|
resourceLock sync.RWMutex
|
||||||
|
|
@ -109,7 +113,7 @@ type ResourceHandler struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create or open resource update chunk store
|
// Create or open resource update chunk store
|
||||||
func NewResourceHandler(privKey *ecdsa.PrivateKey, datadir string, cloudStore CloudStore, ethapi *rpc.Client) (*ResourceHandler, error) {
|
func NewResourceHandler(privKey *ecdsa.PrivateKey, datadir string, cloudStore CloudStore, rpcclient *rpc.Client, ensAddr common.Address) (*ResourceHandler, error) {
|
||||||
path := filepath.Join(datadir, "resource")
|
path := filepath.Join(datadir, "resource")
|
||||||
dbStore, err := NewDbStore(datadir, nil, singletonSwarmDbCapacity, 0)
|
dbStore, err := NewDbStore(datadir, nil, singletonSwarmDbCapacity, 0)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -120,9 +124,17 @@ func NewResourceHandler(privKey *ecdsa.PrivateKey, datadir string, cloudStore Cl
|
||||||
DbStore: dbStore,
|
DbStore: dbStore,
|
||||||
}
|
}
|
||||||
hasher := MakeHashFunc("SHA3")
|
hasher := MakeHashFunc("SHA3")
|
||||||
|
transactOpts := bind.NewKeyedTransactor(privKey)
|
||||||
|
ethapi := ethclient.NewClient(rpcclient)
|
||||||
|
ensinstance, err := ens.NewENS(transactOpts, ensAddr, ethapi)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
return &ResourceHandler{
|
return &ResourceHandler{
|
||||||
ChunkStore: newResourceChunkStore(path, hasher, localStore, cloudStore),
|
ChunkStore: newResourceChunkStore(path, hasher, localStore, cloudStore),
|
||||||
ethapi: ethapi,
|
ethapi: ethclient.NewClient(rpcclient),
|
||||||
|
rpcClient: rpcclient,
|
||||||
|
ensapi: ensinstance,
|
||||||
resources: make(map[string]*resource),
|
resources: make(map[string]*resource),
|
||||||
hasher: hasher(),
|
hasher: hasher(),
|
||||||
privKey: privKey,
|
privKey: privKey,
|
||||||
|
|
@ -519,7 +531,7 @@ func (self *ResourceHandler) Close() {
|
||||||
func (self *ResourceHandler) getBlock() (uint64, error) {
|
func (self *ResourceHandler) getBlock() (uint64, error) {
|
||||||
// get the block height and convert to uint64
|
// get the block height and convert to uint64
|
||||||
var currentblock string
|
var currentblock string
|
||||||
err := self.ethapi.Call(¤tblock, "eth_blockNumber")
|
err := self.rpcClient.Call(¤tblock, "eth_blockNumber")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,7 @@ import (
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/accounts/abi/bind"
|
"github.com/ethereum/go-ethereum/accounts/abi/bind"
|
||||||
"github.com/ethereum/go-ethereum/accounts/abi/bind/backends"
|
"github.com/ethereum/go-ethereum/accounts/abi/bind/backends"
|
||||||
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/contracts/ens"
|
"github.com/ethereum/go-ethereum/contracts/ens"
|
||||||
"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"
|
||||||
|
|
@ -29,26 +30,46 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
zeroAddr = common.Address{}
|
||||||
blockCount = uint64(4200)
|
blockCount = uint64(4200)
|
||||||
cleanF func()
|
cleanF func()
|
||||||
hashfunc = sha3.NewKeccak256()
|
hashfunc = sha3.NewKeccak256()
|
||||||
|
domainName = "føø.bar"
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
log.Root().SetHandler(log.CallerFileHandler(log.LvlFilterHandler(log.LvlTrace, log.StreamHandler(os.Stderr, log.TerminalFormat(true)))))
|
log.Root().SetHandler(log.CallerFileHandler(log.LvlFilterHandler(log.LvlTrace, log.StreamHandler(os.Stderr, log.TerminalFormat(true)))))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type fakeBackend struct {
|
||||||
|
*backends.SimulatedBackend
|
||||||
|
blocknumber uint64
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *fakeBackend) Commit() {
|
||||||
|
if f.SimulatedBackend != nil {
|
||||||
|
f.SimulatedBackend.Commit()
|
||||||
|
}
|
||||||
|
f.blocknumber++
|
||||||
|
}
|
||||||
|
|
||||||
type FakeRPC struct {
|
type FakeRPC struct {
|
||||||
blockcount *uint64
|
backend *fakeBackend
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *FakeRPC) BlockNumber() (string, error) {
|
func (r *FakeRPC) BlockNumber() (string, error) {
|
||||||
return strconv.FormatUint(*r.blockcount, 10), nil
|
return strconv.FormatUint(r.backend.blocknumber, 10), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestResourceValidContent(t *testing.T) {
|
func TestResourceValidContent(t *testing.T) {
|
||||||
|
|
||||||
rh, privkey, _, err, teardownTest := setupTest()
|
// privkey for signing updates
|
||||||
|
privkey, err := crypto.GenerateKey()
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
rh, _, err, teardownTest := setupTest(privkey, nil, zeroAddr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
teardownTest(t, err)
|
teardownTest(t, err)
|
||||||
}
|
}
|
||||||
|
|
@ -97,8 +118,14 @@ func TestResourceValidContent(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestResourceReverseLookup(t *testing.T) {
|
func TestResourceReverseLookup(t *testing.T) {
|
||||||
//rh, privkey, datadir, err, teardownTest := setupTest()
|
|
||||||
rh, _, _, err, teardownTest := setupTest()
|
// privkey for signing updates
|
||||||
|
privkey, err := crypto.GenerateKey()
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
rh, _, err, teardownTest := setupTest(privkey, nil, zeroAddr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
teardownTest(t, err)
|
teardownTest(t, err)
|
||||||
}
|
}
|
||||||
|
|
@ -149,7 +176,13 @@ func TestResourceReverseLookup(t *testing.T) {
|
||||||
|
|
||||||
func TestResourceHandler(t *testing.T) {
|
func TestResourceHandler(t *testing.T) {
|
||||||
|
|
||||||
rh, privkey, datadir, err, teardownTest := setupTest()
|
// privkey for signing updates
|
||||||
|
privkey, err := crypto.GenerateKey()
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
rh, datadir, err, teardownTest := setupTest(privkey, nil, zeroAddr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
teardownTest(t, err)
|
teardownTest(t, err)
|
||||||
}
|
}
|
||||||
|
|
@ -218,7 +251,7 @@ func TestResourceHandler(t *testing.T) {
|
||||||
// it will match on second iteration startblocknumber + (resourcefrequency * 3)
|
// it will match on second iteration startblocknumber + (resourcefrequency * 3)
|
||||||
blockCount = startblocknumber + (resourcefrequency * 4)
|
blockCount = startblocknumber + (resourcefrequency * 4)
|
||||||
|
|
||||||
rh2, err := NewResourceHandler(privkey, datadir, &testCloudStore{}, rh.ethapi)
|
rh2, err := NewResourceHandler(privkey, datadir, &testCloudStore{}, rh.rpcClient, ens.MainNetAddress)
|
||||||
_, err = rh2.LookupLatest(resourcename, true)
|
_, err = rh2.LookupLatest(resourcename, true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
teardownTest(t, err)
|
teardownTest(t, err)
|
||||||
|
|
@ -280,7 +313,33 @@ func TestResourceHandler(t *testing.T) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func setupTest() (rh *ResourceHandler, privkey *ecdsa.PrivateKey, datadir string, err error, teardown func(*testing.T, error)) {
|
func TestResourceENS(t *testing.T) {
|
||||||
|
|
||||||
|
// privkey for signing updates
|
||||||
|
privkey, err := crypto.GenerateKey()
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
domainparts := strings.Split(domainName, ".")
|
||||||
|
addr, contractbackend, err := setupENS(privkey, domainparts[0], domainparts[1])
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
rh, _, err, teardownTest := setupTest(privkey, contractbackend, addr)
|
||||||
|
if err != nil {
|
||||||
|
teardownTest(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = rh.NewResource(domainName, 42)
|
||||||
|
if err != nil {
|
||||||
|
teardownTest(t, err)
|
||||||
|
}
|
||||||
|
teardownTest(t, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
func setupTest(privkey *ecdsa.PrivateKey, contractbackend bind.ContractBackend, ensaddr common.Address) (rh *ResourceHandler, datadir string, err error, teardown func(*testing.T, error)) {
|
||||||
|
|
||||||
var fsClean func()
|
var fsClean func()
|
||||||
var rpcClean func()
|
var rpcClean func()
|
||||||
|
|
@ -293,12 +352,6 @@ func setupTest() (rh *ResourceHandler, privkey *ecdsa.PrivateKey, datadir string
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// privkey for signing updates
|
|
||||||
privkey, err = crypto.GenerateKey()
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// temp datadir
|
// temp datadir
|
||||||
datadir, err = ioutil.TempDir("", "rh")
|
datadir, err = ioutil.TempDir("", "rh")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -316,8 +369,12 @@ func setupTest() (rh *ResourceHandler, privkey *ecdsa.PrivateKey, datadir string
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
rpcserver := rpc.NewServer()
|
rpcserver := rpc.NewServer()
|
||||||
|
var fake *fakeBackend
|
||||||
|
if contractbackend != nil {
|
||||||
|
fake = contractbackend.(*fakeBackend)
|
||||||
|
}
|
||||||
rpcserver.RegisterName("eth", &FakeRPC{
|
rpcserver.RegisterName("eth", &FakeRPC{
|
||||||
blockcount: &blockCount,
|
backend: fake,
|
||||||
})
|
})
|
||||||
go func() {
|
go func() {
|
||||||
rpcserver.ServeListener(ipcl)
|
rpcserver.ServeListener(ipcl)
|
||||||
|
|
@ -332,7 +389,7 @@ func setupTest() (rh *ResourceHandler, privkey *ecdsa.PrivateKey, datadir string
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
rh, err = NewResourceHandler(privkey, datadir, &testCloudStore{}, rpcclient)
|
rh, err = NewResourceHandler(privkey, datadir, &testCloudStore{}, rpcclient, ensaddr)
|
||||||
teardown = func(t *testing.T, err error) {
|
teardown = func(t *testing.T, err error) {
|
||||||
cleanF()
|
cleanF()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -342,22 +399,7 @@ func setupTest() (rh *ResourceHandler, privkey *ecdsa.PrivateKey, datadir string
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
func setupENS(privkey *ecdsa.PrivateKey, sub string, top string) (common.Address, bind.ContractBackend, error) {
|
||||||
func TestResourceENS(t *testing.T) {
|
|
||||||
_, privkey, _, err, teardownTest := setupTest()
|
|
||||||
if err != nil {
|
|
||||||
teardownTest(t, err)
|
|
||||||
}
|
|
||||||
err = setupENS(privkey, "foo", "bar")
|
|
||||||
if err != nil {
|
|
||||||
teardownTest(t, err)
|
|
||||||
}
|
|
||||||
teardownTest(t, nil)
|
|
||||||
}
|
|
||||||
|
|
||||||
func setupENS(privkey *ecdsa.PrivateKey, sub string, top string) error {
|
|
||||||
// ens backend
|
|
||||||
//key := crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
|
|
||||||
var tophash [32]byte
|
var tophash [32]byte
|
||||||
var subhash [32]byte
|
var subhash [32]byte
|
||||||
hashfunc.Reset()
|
hashfunc.Reset()
|
||||||
|
|
@ -367,45 +409,39 @@ func setupENS(privkey *ecdsa.PrivateKey, sub string, top string) error {
|
||||||
hashfunc.Write([]byte(sub))
|
hashfunc.Write([]byte(sub))
|
||||||
copy(subhash[:], hashfunc.Sum(nil))
|
copy(subhash[:], hashfunc.Sum(nil))
|
||||||
addr := crypto.PubkeyToAddress(privkey.PublicKey)
|
addr := crypto.PubkeyToAddress(privkey.PublicKey)
|
||||||
contractBackend := backends.NewSimulatedBackend(core.GenesisAlloc{addr: {Balance: big.NewInt(1000000000)}})
|
contractBackend := &fakeBackend{
|
||||||
|
SimulatedBackend: backends.NewSimulatedBackend(core.GenesisAlloc{addr: {Balance: big.NewInt(1000000000)}}),
|
||||||
|
}
|
||||||
transactOpts := bind.NewKeyedTransactor(privkey)
|
transactOpts := bind.NewKeyedTransactor(privkey)
|
||||||
|
|
||||||
_, _, ensinstance, err := contract.DeployENS(transactOpts, contractBackend)
|
ensAddr, _, ensinstance, err := contract.DeployENS(transactOpts, contractBackend)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("can't deploy: %v", err)
|
return zeroAddr, nil, fmt.Errorf("can't deploy: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Deploy the registrar.
|
|
||||||
// regAddr, _, reginstance, err := contract.DeployFIFSRegistrar(transactOpts, contractBackend, ensAddr, [32]byte{})
|
|
||||||
// if err != nil {
|
|
||||||
// return fmt.Errorf("can't deploy Registrar: %v", err)
|
|
||||||
// }
|
|
||||||
// contractBackend.Commit()
|
|
||||||
//
|
|
||||||
// Set the registrar as owner of the ENS root.
|
|
||||||
if _, err = ensinstance.SetOwner(transactOpts, [32]byte{}, addr); err != nil {
|
if _, err = ensinstance.SetOwner(transactOpts, [32]byte{}, addr); err != nil {
|
||||||
return fmt.Errorf("can't setowner: %v", err)
|
return zeroAddr, nil, fmt.Errorf("can't setowner: %v", err)
|
||||||
}
|
}
|
||||||
contractBackend.Commit()
|
contractBackend.Commit()
|
||||||
|
|
||||||
if _, err = ensinstance.SetSubnodeOwner(transactOpts, [32]byte{}, tophash, addr); err != nil {
|
if _, err = ensinstance.SetSubnodeOwner(transactOpts, [32]byte{}, tophash, addr); err != nil {
|
||||||
return fmt.Errorf("can't register top: %v", err)
|
return zeroAddr, nil, fmt.Errorf("can't register top: %v", err)
|
||||||
}
|
}
|
||||||
contractBackend.Commit()
|
contractBackend.Commit()
|
||||||
|
|
||||||
if _, err = ensinstance.SetSubnodeOwner(transactOpts, ens.EnsNode(top), subhash, addr); err != nil {
|
if _, err = ensinstance.SetSubnodeOwner(transactOpts, ens.EnsNode(top), subhash, addr); err != nil {
|
||||||
return fmt.Errorf("can't register top: %v", err)
|
return zeroAddr, nil, fmt.Errorf("can't register top: %v", err)
|
||||||
}
|
}
|
||||||
contractBackend.Commit()
|
contractBackend.Commit()
|
||||||
|
|
||||||
nodeowner, err := ensinstance.Owner(&bind.CallOpts{}, ens.EnsNode(strings.Join([]string{sub, top}, ".")))
|
nodeowner, err := ensinstance.Owner(&bind.CallOpts{}, ens.EnsNode(strings.Join([]string{sub, top}, ".")))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("can't retrieve owner: %v", err)
|
return zeroAddr, nil, fmt.Errorf("can't retrieve owner: %v", err)
|
||||||
} else if !bytes.Equal(nodeowner.Bytes(), addr.Bytes()) {
|
} else if !bytes.Equal(nodeowner.Bytes(), addr.Bytes()) {
|
||||||
return fmt.Errorf("retrieved owner doesn't match; expected '%x', got '%x'", addr, nodeowner)
|
return zeroAddr, nil, fmt.Errorf("retrieved owner doesn't match; expected '%x', got '%x'", addr, nodeowner)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return ensAddr, contractBackend, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type testCloudStore struct {
|
type testCloudStore struct {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue