Commit eb445d9c authored by Esad Akar's avatar Esad Akar Committed by GitHub

feat: non-mineable overlays (#2108)

parent d0da9fbb
...@@ -61,6 +61,7 @@ const ( ...@@ -61,6 +61,7 @@ const (
optionNameSwapInitialDeposit = "swap-initial-deposit" optionNameSwapInitialDeposit = "swap-initial-deposit"
optionNameSwapEnable = "swap-enable" optionNameSwapEnable = "swap-enable"
optionNameTransactionHash = "transaction" optionNameTransactionHash = "transaction"
optionNameBlockHash = "block-hash"
optionNameSwapDeploymentGasPrice = "swap-deployment-gas-price" optionNameSwapDeploymentGasPrice = "swap-deployment-gas-price"
optionNameFullNode = "full-node" optionNameFullNode = "full-node"
optionNamePostageContractAddress = "postage-stamp-address" optionNamePostageContractAddress = "postage-stamp-address"
...@@ -238,6 +239,7 @@ func (c *command) setAllFlags(cmd *cobra.Command) { ...@@ -238,6 +239,7 @@ func (c *command) setAllFlags(cmd *cobra.Command) {
cmd.Flags().String(optionNamePostageContractAddress, "", "postage stamp contract address") cmd.Flags().String(optionNamePostageContractAddress, "", "postage stamp contract address")
cmd.Flags().String(optionNamePriceOracleAddress, "", "price oracle contract address") cmd.Flags().String(optionNamePriceOracleAddress, "", "price oracle contract address")
cmd.Flags().String(optionNameTransactionHash, "", "proof-of-identity transaction hash") cmd.Flags().String(optionNameTransactionHash, "", "proof-of-identity transaction hash")
cmd.Flags().String(optionNameBlockHash, "", "block hash of the block whose parent is the block that contains the transaction hash")
cmd.Flags().Uint64(optionNameBlockTime, 15, "chain block time") cmd.Flags().Uint64(optionNameBlockTime, 15, "chain block time")
cmd.Flags().String(optionNameSwapDeploymentGasPrice, "", "gas price in wei to use for deployment and funding") cmd.Flags().String(optionNameSwapDeploymentGasPrice, "", "gas price in wei to use for deployment and funding")
cmd.Flags().Duration(optionWarmUpTime, time.Minute*10, "time to warmup the node before pull/push protocols can be kicked off.") cmd.Flags().Duration(optionWarmUpTime, time.Minute*10, "time to warmup the node before pull/push protocols can be kicked off.")
......
...@@ -7,7 +7,9 @@ package cmd ...@@ -7,7 +7,9 @@ package cmd
import ( import (
"fmt" "fmt"
"strings" "strings"
"time"
"github.com/ethersphere/bee/pkg/crypto"
"github.com/ethersphere/bee/pkg/node" "github.com/ethersphere/bee/pkg/node"
"github.com/spf13/cobra" "github.com/spf13/cobra"
) )
...@@ -34,6 +36,7 @@ func (c *command) initDeployCmd() error { ...@@ -34,6 +36,7 @@ func (c *command) initDeployCmd() error {
swapInitialDeposit := c.config.GetString(optionNameSwapInitialDeposit) swapInitialDeposit := c.config.GetString(optionNameSwapInitialDeposit)
swapEndpoint := c.config.GetString(optionNameSwapEndpoint) swapEndpoint := c.config.GetString(optionNameSwapEndpoint)
deployGasPrice := c.config.GetString(optionNameSwapDeploymentGasPrice) deployGasPrice := c.config.GetString(optionNameSwapDeploymentGasPrice)
networkID := c.config.GetUint64(optionNameNetworkID)
stateStore, err := node.InitStateStore(logger, dataDir) stateStore, err := node.InitStateStore(logger, dataDir)
if err != nil { if err != nil {
...@@ -48,11 +51,6 @@ func (c *command) initDeployCmd() error { ...@@ -48,11 +51,6 @@ func (c *command) initDeployCmd() error {
} }
signer := signerConfig.signer signer := signerConfig.signer
err = node.CheckOverlayWithStore(signerConfig.address, stateStore)
if err != nil {
return err
}
ctx := cmd.Context() ctx := cmd.Context()
swapBackend, overlayEthAddress, chainID, transactionMonitor, transactionService, err := node.InitChain( swapBackend, overlayEthAddress, chainID, transactionMonitor, transactionService, err := node.InitChain(
...@@ -94,6 +92,33 @@ func (c *command) initDeployCmd() error { ...@@ -94,6 +92,33 @@ func (c *command) initDeployCmd() error {
swapInitialDeposit, swapInitialDeposit,
deployGasPrice, deployGasPrice,
) )
if err != nil {
return err
}
optionTrxHash := c.config.GetString(optionNameTransactionHash)
optionBlockHash := c.config.GetString(optionNameBlockHash)
txHash, err := node.GetTxHash(stateStore, logger, optionTrxHash)
if err != nil {
return fmt.Errorf("invalid transaction hash: %w", err)
}
blockTime := time.Duration(c.config.GetUint64(optionNameBlockTime)) * time.Second
blockHash, err := node.GetTxNextBlock(ctx, logger, swapBackend, transactionMonitor, blockTime, txHash, optionBlockHash)
if err != nil {
return err
}
pubKey, err := signer.PublicKey()
if err != nil {
return err
}
swarmAddress, err := crypto.NewOverlayAddress(*pubKey, networkID, blockHash)
err = node.CheckOverlayWithStore(swarmAddress, stateStore)
return err return err
}, },
......
...@@ -26,7 +26,7 @@ func (c *command) initInitCmd() (err error) { ...@@ -26,7 +26,7 @@ func (c *command) initInitCmd() (err error) {
if err != nil { if err != nil {
return fmt.Errorf("new logger: %v", err) return fmt.Errorf("new logger: %v", err)
} }
signerConfig, err := c.configureSigner(cmd, logger) _, err = c.configureSigner(cmd, logger)
if err != nil { if err != nil {
return err return err
} }
...@@ -39,7 +39,7 @@ func (c *command) initInitCmd() (err error) { ...@@ -39,7 +39,7 @@ func (c *command) initInitCmd() (err error) {
defer stateStore.Close() defer stateStore.Close()
return node.CheckOverlayWithStore(signerConfig.address, stateStore) return nil
}, },
PreRunE: func(cmd *cobra.Command, args []string) error { PreRunE: func(cmd *cobra.Command, args []string) error {
return c.config.BindPFlags(cmd.Flags()) return c.config.BindPFlags(cmd.Flags())
......
...@@ -31,7 +31,6 @@ import ( ...@@ -31,7 +31,6 @@ import (
"github.com/ethersphere/bee/pkg/logging" "github.com/ethersphere/bee/pkg/logging"
"github.com/ethersphere/bee/pkg/node" "github.com/ethersphere/bee/pkg/node"
"github.com/ethersphere/bee/pkg/resolver/multiresolver" "github.com/ethersphere/bee/pkg/resolver/multiresolver"
"github.com/ethersphere/bee/pkg/swarm"
"github.com/kardianos/service" "github.com/kardianos/service"
"github.com/spf13/cobra" "github.com/spf13/cobra"
) )
...@@ -116,7 +115,7 @@ Welcome to the Swarm.... Bzzz Bzzzz Bzzzz ...@@ -116,7 +115,7 @@ Welcome to the Swarm.... Bzzz Bzzzz Bzzzz
return errors.New("boot node must be started as a full node") return errors.New("boot node must be started as a full node")
} }
b, err := node.NewBee(c.config.GetString(optionNameP2PAddr), signerConfig.address, *signerConfig.publicKey, signerConfig.signer, c.config.GetUint64(optionNameNetworkID), logger, signerConfig.libp2pPrivateKey, signerConfig.pssPrivateKey, node.Options{ b, err := node.NewBee(c.config.GetString(optionNameP2PAddr), signerConfig.publicKey, signerConfig.signer, c.config.GetUint64(optionNameNetworkID), logger, signerConfig.libp2pPrivateKey, signerConfig.pssPrivateKey, &node.Options{
DataDir: c.config.GetString(optionNameDataDir), DataDir: c.config.GetString(optionNameDataDir),
CacheCapacity: c.config.GetUint64(optionNameCacheCapacity), CacheCapacity: c.config.GetUint64(optionNameCacheCapacity),
DBOpenFilesLimit: c.config.GetUint64(optionNameDBOpenFilesLimit), DBOpenFilesLimit: c.config.GetUint64(optionNameDBOpenFilesLimit),
...@@ -151,6 +150,7 @@ Welcome to the Swarm.... Bzzz Bzzzz Bzzzz ...@@ -151,6 +150,7 @@ Welcome to the Swarm.... Bzzz Bzzzz Bzzzz
SwapEnable: c.config.GetBool(optionNameSwapEnable), SwapEnable: c.config.GetBool(optionNameSwapEnable),
FullNodeMode: fullNode, FullNodeMode: fullNode,
Transaction: c.config.GetString(optionNameTransactionHash), Transaction: c.config.GetString(optionNameTransactionHash),
BlockHash: c.config.GetString(optionNameBlockHash),
PostageContractAddress: c.config.GetString(optionNamePostageContractAddress), PostageContractAddress: c.config.GetString(optionNamePostageContractAddress),
PriceOracleAddress: c.config.GetString(optionNamePriceOracleAddress), PriceOracleAddress: c.config.GetString(optionNamePriceOracleAddress),
BlockTime: c.config.GetUint64(optionNameBlockTime), BlockTime: c.config.GetUint64(optionNameBlockTime),
...@@ -247,7 +247,6 @@ func (p *program) Stop(s service.Service) error { ...@@ -247,7 +247,6 @@ func (p *program) Stop(s service.Service) error {
type signerConfig struct { type signerConfig struct {
signer crypto.Signer signer crypto.Signer
address swarm.Address
publicKey *ecdsa.PublicKey publicKey *ecdsa.PublicKey
libp2pPrivateKey *ecdsa.PrivateKey libp2pPrivateKey *ecdsa.PrivateKey
pssPrivateKey *ecdsa.PrivateKey pssPrivateKey *ecdsa.PrivateKey
...@@ -279,7 +278,6 @@ func (c *command) configureSigner(cmd *cobra.Command, logger logging.Logger) (co ...@@ -279,7 +278,6 @@ func (c *command) configureSigner(cmd *cobra.Command, logger logging.Logger) (co
} }
var signer crypto.Signer var signer crypto.Signer
var address swarm.Address
var password string var password string
var publicKey *ecdsa.PublicKey var publicKey *ecdsa.PublicKey
if p := c.config.GetString(optionNamePassword); p != "" { if p := c.config.GetString(optionNamePassword); p != "" {
...@@ -347,32 +345,14 @@ func (c *command) configureSigner(cmd *cobra.Command, logger logging.Logger) (co ...@@ -347,32 +345,14 @@ func (c *command) configureSigner(cmd *cobra.Command, logger logging.Logger) (co
if err != nil { if err != nil {
return nil, err return nil, err
} }
address, err = crypto.NewOverlayAddress(*publicKey, c.config.GetUint64(optionNameNetworkID))
if err != nil {
return nil, err
}
logger.Infof("using swarm network address through clef: %s", address)
} else { } else {
logger.Warning("clef is not enabled; portability and security of your keys is sub optimal") logger.Warning("clef is not enabled; portability and security of your keys is sub optimal")
swarmPrivateKey, created, err := keystore.Key("swarm", password) swarmPrivateKey, _, err := keystore.Key("swarm", password)
if err != nil { if err != nil {
return nil, fmt.Errorf("swarm key: %w", err) return nil, fmt.Errorf("swarm key: %w", err)
} }
signer = crypto.NewDefaultSigner(swarmPrivateKey) signer = crypto.NewDefaultSigner(swarmPrivateKey)
publicKey = &swarmPrivateKey.PublicKey publicKey = &swarmPrivateKey.PublicKey
address, err = crypto.NewOverlayAddress(*publicKey, c.config.GetUint64(optionNameNetworkID))
if err != nil {
return nil, err
}
if created {
logger.Infof("new swarm network address created: %s", address)
} else {
logger.Infof("using existing swarm network address: %s", address)
}
} }
logger.Infof("swarm public key %x", crypto.EncodeSecp256k1PublicKey(publicKey)) logger.Infof("swarm public key %x", crypto.EncodeSecp256k1PublicKey(publicKey))
...@@ -408,7 +388,6 @@ func (c *command) configureSigner(cmd *cobra.Command, logger logging.Logger) (co ...@@ -408,7 +388,6 @@ func (c *command) configureSigner(cmd *cobra.Command, logger logging.Logger) (co
return &signerConfig{ return &signerConfig{
signer: signer, signer: signer,
address: address,
publicKey: publicKey, publicKey: publicKey,
libp2pPrivateKey: libp2pPrivateKey, libp2pPrivateKey: libp2pPrivateKey,
pssPrivateKey: pssPrivateKey, pssPrivateKey: pssPrivateKey,
......
...@@ -22,7 +22,6 @@ require ( ...@@ -22,7 +22,6 @@ require (
github.com/gorilla/mux v1.7.4 github.com/gorilla/mux v1.7.4
github.com/gorilla/websocket v1.4.2 github.com/gorilla/websocket v1.4.2
github.com/hashicorp/go-multierror v1.1.1 github.com/hashicorp/go-multierror v1.1.1
github.com/hashicorp/golang-lru v0.5.4
github.com/kardianos/service v1.2.0 github.com/kardianos/service v1.2.0
github.com/koron/go-ssdp v0.0.2 // indirect github.com/koron/go-ssdp v0.0.2 // indirect
github.com/kr/text v0.2.0 // indirect github.com/kr/text v0.2.0 // indirect
...@@ -65,14 +64,12 @@ require ( ...@@ -65,14 +64,12 @@ require (
go.uber.org/multierr v1.6.0 // indirect go.uber.org/multierr v1.6.0 // indirect
go.uber.org/zap v1.16.0 // indirect go.uber.org/zap v1.16.0 // indirect
golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad
golang.org/x/mod v0.3.0 // indirect
golang.org/x/net v0.0.0-20201224014010-6772e930b67b golang.org/x/net v0.0.0-20201224014010-6772e930b67b
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9 golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9
golang.org/x/sys v0.0.0-20210108172913-0df2131ae363 golang.org/x/sys v0.0.0-20210108172913-0df2131ae363
golang.org/x/term v0.0.0-20201210144234-2321bbc49cbf golang.org/x/term v0.0.0-20201210144234-2321bbc49cbf
golang.org/x/text v0.3.4 // indirect golang.org/x/text v0.3.4 // indirect
golang.org/x/time v0.0.0-20191024005414-555d28b269f0 golang.org/x/time v0.0.0-20191024005414-555d28b269f0
golang.org/x/tools v0.0.0-20200626171337-aa94e735be7f // indirect
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f // indirect gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f // indirect
gopkg.in/ini.v1 v1.57.0 // indirect gopkg.in/ini.v1 v1.57.0 // indirect
gopkg.in/yaml.v2 v2.3.0 gopkg.in/yaml.v2 v2.3.0
......
...@@ -967,7 +967,6 @@ github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q ...@@ -967,7 +967,6 @@ github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
github.com/xtaci/kcp-go v5.4.20+incompatible/go.mod h1:bN6vIwHQbfHaHtFpEssmWsN45a+AZwO7eyRCmEIbtvE= github.com/xtaci/kcp-go v5.4.20+incompatible/go.mod h1:bN6vIwHQbfHaHtFpEssmWsN45a+AZwO7eyRCmEIbtvE=
github.com/xtaci/lossyconn v0.0.0-20190602105132-8df528c0c9ae/go.mod h1:gXtu8J62kEgmN++bm9BVICuT/e8yiLI2KFobd/TRFsE= github.com/xtaci/lossyconn v0.0.0-20190602105132-8df528c0c9ae/go.mod h1:gXtu8J62kEgmN++bm9BVICuT/e8yiLI2KFobd/TRFsE=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
gitlab.com/nolash/go-mockbytes v0.0.7 h1:9XVFpEfY67kGBVJve3uV19kzqORdlo7V+q09OE6Yo54= gitlab.com/nolash/go-mockbytes v0.0.7 h1:9XVFpEfY67kGBVJve3uV19kzqORdlo7V+q09OE6Yo54=
gitlab.com/nolash/go-mockbytes v0.0.7/go.mod h1:KKOpNTT39j2Eo+P6uUTOncntfeKY6AFh/2CxuD5MpgE= gitlab.com/nolash/go-mockbytes v0.0.7/go.mod h1:KKOpNTT39j2Eo+P6uUTOncntfeKY6AFh/2CxuD5MpgE=
go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
...@@ -1053,10 +1052,8 @@ golang.org/x/mobile v0.0.0-20200801112145-973feb4309de/go.mod h1:skQtrUTUwhdJvXM ...@@ -1053,10 +1052,8 @@ golang.org/x/mobile v0.0.0-20200801112145-973feb4309de/go.mod h1:skQtrUTUwhdJvXM
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
golang.org/x/mod v0.1.1-0.20191209134235-331c550502dd h1:ePuNC7PZ6O5BzgPn9bZayERXBdfZjUYoXEf5BTfDfh8=
golang.org/x/mod v0.1.1-0.20191209134235-331c550502dd/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.1.1-0.20191209134235-331c550502dd/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0 h1:RM4zey1++hCTbCVQfnWeKs9/IEsaBLA8vTkd0WVtmH4=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
...@@ -1084,7 +1081,6 @@ golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLL ...@@ -1084,7 +1081,6 @@ golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLL
golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200320220750-118fecf932d8/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200320220750-118fecf932d8/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
...@@ -1203,9 +1199,8 @@ golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtn ...@@ -1203,9 +1199,8 @@ golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtn
golang.org/x/tools v0.0.0-20191216052735-49a3e744a425/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20191216052735-49a3e744a425/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200117012304-6edc0a871e69/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200117012304-6edc0a871e69/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200221224223-e1da425f72fd h1:hHkvGJK23seRCflePJnVa9IMv8fsuavSCWKd11kDQFs=
golang.org/x/tools v0.0.0-20200221224223-e1da425f72fd/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200221224223-e1da425f72fd/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200626171337-aa94e735be7f h1:JcoF/bowzCDI+MXu1yLqQGNO3ibqWsWq+Sk7pOT218w=
golang.org/x/tools v0.0.0-20200626171337-aa94e735be7f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
......
...@@ -7,6 +7,7 @@ package addressbook_test ...@@ -7,6 +7,7 @@ package addressbook_test
import ( import (
"testing" "testing"
"github.com/ethereum/go-ethereum/common"
"github.com/ethersphere/bee/pkg/addressbook" "github.com/ethersphere/bee/pkg/addressbook"
"github.com/ethersphere/bee/pkg/bzz" "github.com/ethersphere/bee/pkg/bzz"
"github.com/ethersphere/bee/pkg/crypto" "github.com/ethersphere/bee/pkg/crypto"
...@@ -30,6 +31,7 @@ func run(t *testing.T, f bookFunc) { ...@@ -30,6 +31,7 @@ func run(t *testing.T, f bookFunc) {
store := f(t) store := f(t)
addr1 := swarm.NewAddress([]byte{0, 1, 2, 3}) addr1 := swarm.NewAddress([]byte{0, 1, 2, 3})
addr2 := swarm.NewAddress([]byte{0, 1, 2, 4}) addr2 := swarm.NewAddress([]byte{0, 1, 2, 4})
trxHash := common.HexToHash("0x1").Bytes()
multiaddr, err := ma.NewMultiaddr("/ip4/1.1.1.1") multiaddr, err := ma.NewMultiaddr("/ip4/1.1.1.1")
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
...@@ -40,7 +42,7 @@ func run(t *testing.T, f bookFunc) { ...@@ -40,7 +42,7 @@ func run(t *testing.T, f bookFunc) {
t.Fatal(err) t.Fatal(err)
} }
bzzAddr, err := bzz.NewAddress(crypto.NewDefaultSigner(pk), multiaddr, addr1, 1) bzzAddr, err := bzz.NewAddress(crypto.NewDefaultSigner(pk), multiaddr, addr1, 1, trxHash)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
......
...@@ -15,6 +15,7 @@ import ( ...@@ -15,6 +15,7 @@ import (
"errors" "errors"
"fmt" "fmt"
"github.com/ethereum/go-ethereum/common"
"github.com/ethersphere/bee/pkg/crypto" "github.com/ethersphere/bee/pkg/crypto"
"github.com/ethersphere/bee/pkg/swarm" "github.com/ethersphere/bee/pkg/swarm"
...@@ -27,18 +28,20 @@ var ErrInvalidAddress = errors.New("invalid address") ...@@ -27,18 +28,20 @@ var ErrInvalidAddress = errors.New("invalid address")
// It consists of a peers underlay (physical) address, overlay (topology) address and signature. // It consists of a peers underlay (physical) address, overlay (topology) address and signature.
// Signature is used to verify the `Overlay/Underlay` pair, as it is based on `underlay|networkID`, signed with the public key of Overlay address // Signature is used to verify the `Overlay/Underlay` pair, as it is based on `underlay|networkID`, signed with the public key of Overlay address
type Address struct { type Address struct {
Underlay ma.Multiaddr Underlay ma.Multiaddr
Overlay swarm.Address Overlay swarm.Address
Signature []byte Signature []byte
Transaction []byte
} }
type addressJSON struct { type addressJSON struct {
Overlay string `json:"overlay"` Overlay string `json:"overlay"`
Underlay string `json:"underlay"` Underlay string `json:"underlay"`
Signature string `json:"signature"` Signature string `json:"signature"`
Transaction string `json:"transaction"`
} }
func NewAddress(signer crypto.Signer, underlay ma.Multiaddr, overlay swarm.Address, networkID uint64) (*Address, error) { func NewAddress(signer crypto.Signer, underlay ma.Multiaddr, overlay swarm.Address, networkID uint64, trx []byte) (*Address, error) {
underlayBinary, err := underlay.MarshalBinary() underlayBinary, err := underlay.MarshalBinary()
if err != nil { if err != nil {
return nil, err return nil, err
...@@ -50,19 +53,20 @@ func NewAddress(signer crypto.Signer, underlay ma.Multiaddr, overlay swarm.Addre ...@@ -50,19 +53,20 @@ func NewAddress(signer crypto.Signer, underlay ma.Multiaddr, overlay swarm.Addre
} }
return &Address{ return &Address{
Underlay: underlay, Underlay: underlay,
Overlay: overlay, Overlay: overlay,
Signature: signature, Signature: signature,
Transaction: trx,
}, nil }, nil
} }
func ParseAddress(underlay, overlay, signature []byte, networkID uint64) (*Address, error) { func ParseAddress(underlay, overlay, signature, trxHash, blockHash []byte, networkID uint64) (*Address, error) {
recoveredPK, err := crypto.Recover(signature, generateSignData(underlay, overlay, networkID)) recoveredPK, err := crypto.Recover(signature, generateSignData(underlay, overlay, networkID))
if err != nil { if err != nil {
return nil, ErrInvalidAddress return nil, ErrInvalidAddress
} }
recoveredOverlay, err := crypto.NewOverlayAddress(*recoveredPK, networkID) recoveredOverlay, err := crypto.NewOverlayAddress(*recoveredPK, networkID, blockHash)
if err != nil { if err != nil {
return nil, ErrInvalidAddress return nil, ErrInvalidAddress
} }
...@@ -76,9 +80,10 @@ func ParseAddress(underlay, overlay, signature []byte, networkID uint64) (*Addre ...@@ -76,9 +80,10 @@ func ParseAddress(underlay, overlay, signature []byte, networkID uint64) (*Addre
} }
return &Address{ return &Address{
Underlay: multiUnderlay, Underlay: multiUnderlay,
Overlay: swarm.NewAddress(overlay), Overlay: swarm.NewAddress(overlay),
Signature: signature, Signature: signature,
Transaction: trxHash,
}, nil }, nil
} }
...@@ -91,14 +96,15 @@ func generateSignData(underlay, overlay []byte, networkID uint64) []byte { ...@@ -91,14 +96,15 @@ func generateSignData(underlay, overlay []byte, networkID uint64) []byte {
} }
func (a *Address) Equal(b *Address) bool { func (a *Address) Equal(b *Address) bool {
return a.Overlay.Equal(b.Overlay) && a.Underlay.Equal(b.Underlay) && bytes.Equal(a.Signature, b.Signature) return a.Overlay.Equal(b.Overlay) && a.Underlay.Equal(b.Underlay) && bytes.Equal(a.Signature, b.Signature) && bytes.Equal(a.Transaction, b.Transaction)
} }
func (a *Address) MarshalJSON() ([]byte, error) { func (a *Address) MarshalJSON() ([]byte, error) {
return json.Marshal(&addressJSON{ return json.Marshal(&addressJSON{
Overlay: a.Overlay.String(), Overlay: a.Overlay.String(),
Underlay: a.Underlay.String(), Underlay: a.Underlay.String(),
Signature: base64.StdEncoding.EncodeToString(a.Signature), Signature: base64.StdEncoding.EncodeToString(a.Signature),
Transaction: common.Bytes2Hex(a.Transaction),
}) })
} }
...@@ -123,11 +129,12 @@ func (a *Address) UnmarshalJSON(b []byte) error { ...@@ -123,11 +129,12 @@ func (a *Address) UnmarshalJSON(b []byte) error {
a.Underlay = m a.Underlay = m
a.Signature, err = base64.StdEncoding.DecodeString(v.Signature) a.Signature, err = base64.StdEncoding.DecodeString(v.Signature)
a.Transaction = common.Hex2Bytes(v.Transaction)
return err return err
} }
func (a *Address) String() string { func (a *Address) String() string {
return fmt.Sprintf("[Underlay: %v, Overlay %v, Signature %x]", a.Underlay, a.Overlay, a.Signature) return fmt.Sprintf("[Underlay: %v, Overlay %v, Signature %x, Transaction %x]", a.Underlay, a.Overlay, a.Signature, a.Transaction)
} }
// ShortString returns shortened versions of bzz address in a format: [Overlay, Underlay] // ShortString returns shortened versions of bzz address in a format: [Overlay, Underlay]
......
...@@ -7,6 +7,7 @@ package bzz_test ...@@ -7,6 +7,7 @@ package bzz_test
import ( import (
"testing" "testing"
"github.com/ethereum/go-ethereum/common"
"github.com/ethersphere/bee/pkg/bzz" "github.com/ethersphere/bee/pkg/bzz"
"github.com/ethersphere/bee/pkg/crypto" "github.com/ethersphere/bee/pkg/crypto"
...@@ -19,23 +20,26 @@ func TestBzzAddress(t *testing.T) { ...@@ -19,23 +20,26 @@ func TestBzzAddress(t *testing.T) {
t.Fatal(err) t.Fatal(err)
} }
trxHash := common.HexToHash("0x1").Bytes()
blockHash := common.HexToHash("0x2").Bytes()
privateKey1, err := crypto.GenerateSecp256k1Key() privateKey1, err := crypto.GenerateSecp256k1Key()
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
overlay, err := crypto.NewOverlayAddress(privateKey1.PublicKey, 3) overlay, err := crypto.NewOverlayAddress(privateKey1.PublicKey, 3, blockHash)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
signer1 := crypto.NewDefaultSigner(privateKey1) signer1 := crypto.NewDefaultSigner(privateKey1)
bzzAddress, err := bzz.NewAddress(signer1, node1ma, overlay, 3) bzzAddress, err := bzz.NewAddress(signer1, node1ma, overlay, 3, trxHash)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
bzzAddress2, err := bzz.ParseAddress(node1ma.Bytes(), overlay.Bytes(), bzzAddress.Signature, 3) bzzAddress2, err := bzz.ParseAddress(node1ma.Bytes(), overlay.Bytes(), bzzAddress.Signature, trxHash, blockHash, 3)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
......
...@@ -20,24 +20,34 @@ import ( ...@@ -20,24 +20,34 @@ import (
// RecoverFunc is a function to recover the public key from a signature // RecoverFunc is a function to recover the public key from a signature
type RecoverFunc func(signature, data []byte) (*ecdsa.PublicKey, error) type RecoverFunc func(signature, data []byte) (*ecdsa.PublicKey, error)
var ErrBadHashLength = errors.New("wrong block hash length")
const ( const (
AddressSize = 20 AddressSize = 20
) )
// NewOverlayAddress constructs a Swarm Address from ECDSA public key. // NewOverlayAddress constructs a Swarm Address from ECDSA public key.
func NewOverlayAddress(p ecdsa.PublicKey, networkID uint64) (swarm.Address, error) { func NewOverlayAddress(p ecdsa.PublicKey, networkID uint64, blockHash []byte) (swarm.Address, error) {
ethAddr, err := NewEthereumAddress(p) ethAddr, err := NewEthereumAddress(p)
if err != nil { if err != nil {
return swarm.ZeroAddress, err return swarm.ZeroAddress, err
} }
return NewOverlayFromEthereumAddress(ethAddr, networkID), nil
if len(blockHash) != 32 {
return swarm.ZeroAddress, ErrBadHashLength
}
return NewOverlayFromEthereumAddress(ethAddr, networkID, blockHash), nil
} }
// NewOverlayFromEthereumAddress constructs a Swarm Address for an Ethereum address. // NewOverlayFromEthereumAddress constructs a Swarm Address for an Ethereum address.
func NewOverlayFromEthereumAddress(ethAddr []byte, networkID uint64) swarm.Address { func NewOverlayFromEthereumAddress(ethAddr []byte, networkID uint64, blockHash []byte) swarm.Address {
netIDBytes := make([]byte, 8) netIDBytes := make([]byte, 8)
binary.LittleEndian.PutUint64(netIDBytes, networkID) binary.LittleEndian.PutUint64(netIDBytes, networkID)
h := sha3.Sum256(append(ethAddr, netIDBytes...)) data := append(ethAddr, netIDBytes...)
data = append(data, blockHash...)
h := sha3.Sum256(data)
return swarm.NewAddress(h[:]) return swarm.NewAddress(h[:])
} }
......
...@@ -7,8 +7,10 @@ package crypto_test ...@@ -7,8 +7,10 @@ package crypto_test
import ( import (
"bytes" "bytes"
"encoding/hex" "encoding/hex"
"errors"
"testing" "testing"
"github.com/ethereum/go-ethereum/common"
"github.com/ethersphere/bee/pkg/crypto" "github.com/ethersphere/bee/pkg/crypto"
) )
...@@ -38,13 +40,18 @@ func TestNewAddress(t *testing.T) { ...@@ -38,13 +40,18 @@ func TestNewAddress(t *testing.T) {
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
a, err := crypto.NewOverlayAddress(k.PublicKey, 1) a, err := crypto.NewOverlayAddress(k.PublicKey, 1, common.HexToHash("0x1").Bytes())
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
if l := len(a.Bytes()); l != 32 { if l := len(a.Bytes()); l != 32 {
t.Errorf("got address length %v, want %v", l, 32) t.Errorf("got address length %v, want %v", l, 32)
} }
_, err = crypto.NewOverlayAddress(k.PublicKey, 1, nil)
if !errors.Is(err, crypto.ErrBadHashLength) {
t.Fatalf("expected %v, got %v", crypto.ErrBadHashLength, err)
}
} }
func TestEncodeSecp256k1PrivateKey(t *testing.T) { func TestEncodeSecp256k1PrivateKey(t *testing.T) {
......
...@@ -33,7 +33,7 @@ import ( ...@@ -33,7 +33,7 @@ import (
// Service implements http.Handler interface to be used in HTTP server. // Service implements http.Handler interface to be used in HTTP server.
type Service struct { type Service struct {
overlay swarm.Address overlay *swarm.Address
publicKey ecdsa.PublicKey publicKey ecdsa.PublicKey
pssPublicKey ecdsa.PublicKey pssPublicKey ecdsa.PublicKey
ethereumAddress common.Address ethereumAddress common.Address
...@@ -63,9 +63,8 @@ type Service struct { ...@@ -63,9 +63,8 @@ type Service struct {
// to expose /addresses, /health endpoints, Go metrics and pprof. It is useful to expose // to expose /addresses, /health endpoints, Go metrics and pprof. It is useful to expose
// these endpoints before all dependencies are configured and injected to have // these endpoints before all dependencies are configured and injected to have
// access to basic debugging tools and /health endpoint. // access to basic debugging tools and /health endpoint.
func New(overlay swarm.Address, publicKey, pssPublicKey ecdsa.PublicKey, ethereumAddress common.Address, logger logging.Logger, tracer *tracing.Tracer, corsAllowedOrigins []string) *Service { func New(publicKey, pssPublicKey ecdsa.PublicKey, ethereumAddress common.Address, logger logging.Logger, tracer *tracing.Tracer, corsAllowedOrigins []string) *Service {
s := new(Service) s := new(Service)
s.overlay = overlay
s.publicKey = publicKey s.publicKey = publicKey
s.pssPublicKey = pssPublicKey s.pssPublicKey = pssPublicKey
s.ethereumAddress = ethereumAddress s.ethereumAddress = ethereumAddress
...@@ -82,7 +81,7 @@ func New(overlay swarm.Address, publicKey, pssPublicKey ecdsa.PublicKey, ethereu ...@@ -82,7 +81,7 @@ func New(overlay swarm.Address, publicKey, pssPublicKey ecdsa.PublicKey, ethereu
// Configure injects required dependencies and configuration parameters and // Configure injects required dependencies and configuration parameters and
// constructs HTTP routes that depend on them. It is intended and safe to call // constructs HTTP routes that depend on them. It is intended and safe to call
// this method only once. // this method only once.
func (s *Service) Configure(p2p p2p.DebugService, pingpong pingpong.Interface, topologyDriver topology.Driver, lightNodes *lightnode.Container, storer storage.Storer, tags *tags.Tags, accounting accounting.Interface, pseudosettle settlement.Interface, chequebookEnabled bool, swap swap.Interface, chequebook chequebook.Service, batchStore postage.Storer, transaction transaction.Service) { func (s *Service) Configure(overlay swarm.Address, p2p p2p.DebugService, pingpong pingpong.Interface, topologyDriver topology.Driver, lightNodes *lightnode.Container, storer storage.Storer, tags *tags.Tags, accounting accounting.Interface, pseudosettle settlement.Interface, chequebookEnabled bool, swap swap.Interface, chequebook chequebook.Service, batchStore postage.Storer, transaction transaction.Service) {
s.p2p = p2p s.p2p = p2p
s.pingpong = pingpong s.pingpong = pingpong
s.topologyDriver = topologyDriver s.topologyDriver = topologyDriver
...@@ -96,6 +95,7 @@ func (s *Service) Configure(p2p p2p.DebugService, pingpong pingpong.Interface, t ...@@ -96,6 +95,7 @@ func (s *Service) Configure(p2p p2p.DebugService, pingpong pingpong.Interface, t
s.batchStore = batchStore s.batchStore = batchStore
s.pseudosettle = pseudosettle s.pseudosettle = pseudosettle
s.transaction = transaction s.transaction = transaction
s.overlay = &overlay
s.setRouter(s.newRouter()) s.setRouter(s.newRouter())
} }
......
...@@ -70,8 +70,8 @@ func newTestServer(t *testing.T, o testServerOptions) *testServer { ...@@ -70,8 +70,8 @@ func newTestServer(t *testing.T, o testServerOptions) *testServer {
swapserv := swapmock.New(o.SwapOpts...) swapserv := swapmock.New(o.SwapOpts...)
transaction := transactionmock.New(o.TransactionOpts...) transaction := transactionmock.New(o.TransactionOpts...)
ln := lightnode.NewContainer(o.Overlay) ln := lightnode.NewContainer(o.Overlay)
s := debugapi.New(o.Overlay, o.PublicKey, o.PSSPublicKey, o.EthereumAddress, logging.New(ioutil.Discard, 0), nil, o.CORSAllowedOrigins) s := debugapi.New(o.PublicKey, o.PSSPublicKey, o.EthereumAddress, logging.New(ioutil.Discard, 0), nil, o.CORSAllowedOrigins)
s.Configure(o.P2P, o.Pingpong, topologyDriver, ln, o.Storer, o.Tags, acc, settlement, true, swapserv, chequebook, o.BatchStore, transaction) s.Configure(o.Overlay, o.P2P, o.Pingpong, topologyDriver, ln, o.Storer, o.Tags, acc, settlement, true, swapserv, chequebook, o.BatchStore, transaction)
ts := httptest.NewServer(s) ts := httptest.NewServer(s)
t.Cleanup(ts.Close) t.Cleanup(ts.Close)
...@@ -138,7 +138,7 @@ func TestServer_Configure(t *testing.T) { ...@@ -138,7 +138,7 @@ func TestServer_Configure(t *testing.T) {
swapserv := swapmock.New(o.SwapOpts...) swapserv := swapmock.New(o.SwapOpts...)
ln := lightnode.NewContainer(o.Overlay) ln := lightnode.NewContainer(o.Overlay)
transaction := transactionmock.New(o.TransactionOpts...) transaction := transactionmock.New(o.TransactionOpts...)
s := debugapi.New(o.Overlay, o.PublicKey, o.PSSPublicKey, o.EthereumAddress, logging.New(ioutil.Discard, 0), nil, nil) s := debugapi.New(o.PublicKey, o.PSSPublicKey, o.EthereumAddress, logging.New(ioutil.Discard, 0), nil, nil)
ts := httptest.NewServer(s) ts := httptest.NewServer(s)
t.Cleanup(ts.Close) t.Cleanup(ts.Close)
...@@ -162,7 +162,6 @@ func TestServer_Configure(t *testing.T) { ...@@ -162,7 +162,6 @@ func TestServer_Configure(t *testing.T) {
) )
jsonhttptest.Request(t, client, http.MethodGet, "/addresses", http.StatusOK, jsonhttptest.Request(t, client, http.MethodGet, "/addresses", http.StatusOK,
jsonhttptest.WithExpectedJSONResponse(debugapi.AddressesResponse{ jsonhttptest.WithExpectedJSONResponse(debugapi.AddressesResponse{
Overlay: o.Overlay,
Underlay: make([]multiaddr.Multiaddr, 0), Underlay: make([]multiaddr.Multiaddr, 0),
Ethereum: o.EthereumAddress, Ethereum: o.EthereumAddress,
PublicKey: hex.EncodeToString(crypto.EncodeSecp256k1PublicKey(&o.PublicKey)), PublicKey: hex.EncodeToString(crypto.EncodeSecp256k1PublicKey(&o.PublicKey)),
...@@ -170,7 +169,7 @@ func TestServer_Configure(t *testing.T) { ...@@ -170,7 +169,7 @@ func TestServer_Configure(t *testing.T) {
}), }),
) )
s.Configure(o.P2P, o.Pingpong, topologyDriver, ln, o.Storer, o.Tags, acc, settlement, true, swapserv, chequebook, nil, transaction) s.Configure(o.Overlay, o.P2P, o.Pingpong, topologyDriver, ln, o.Storer, o.Tags, acc, settlement, true, swapserv, chequebook, nil, transaction)
testBasicRouter(t, client) testBasicRouter(t, client)
jsonhttptest.Request(t, client, http.MethodGet, "/readiness", http.StatusOK, jsonhttptest.Request(t, client, http.MethodGet, "/readiness", http.StatusOK,
...@@ -181,7 +180,7 @@ func TestServer_Configure(t *testing.T) { ...@@ -181,7 +180,7 @@ func TestServer_Configure(t *testing.T) {
) )
jsonhttptest.Request(t, client, http.MethodGet, "/addresses", http.StatusOK, jsonhttptest.Request(t, client, http.MethodGet, "/addresses", http.StatusOK,
jsonhttptest.WithExpectedJSONResponse(debugapi.AddressesResponse{ jsonhttptest.WithExpectedJSONResponse(debugapi.AddressesResponse{
Overlay: o.Overlay, Overlay: &o.Overlay,
Underlay: addresses, Underlay: addresses,
Ethereum: o.EthereumAddress, Ethereum: o.EthereumAddress,
PublicKey: hex.EncodeToString(crypto.EncodeSecp256k1PublicKey(&o.PublicKey)), PublicKey: hex.EncodeToString(crypto.EncodeSecp256k1PublicKey(&o.PublicKey)),
......
...@@ -16,7 +16,7 @@ import ( ...@@ -16,7 +16,7 @@ import (
) )
type addressesResponse struct { type addressesResponse struct {
Overlay swarm.Address `json:"overlay"` Overlay *swarm.Address `json:"overlay"`
Underlay []multiaddr.Multiaddr `json:"underlay"` Underlay []multiaddr.Multiaddr `json:"underlay"`
Ethereum common.Address `json:"ethereum"` Ethereum common.Address `json:"ethereum"`
PublicKey string `json:"publicKey"` PublicKey string `json:"publicKey"`
......
...@@ -51,7 +51,7 @@ func TestAddresses(t *testing.T) { ...@@ -51,7 +51,7 @@ func TestAddresses(t *testing.T) {
t.Run("ok", func(t *testing.T) { t.Run("ok", func(t *testing.T) {
jsonhttptest.Request(t, testServer.Client, http.MethodGet, "/addresses", http.StatusOK, jsonhttptest.Request(t, testServer.Client, http.MethodGet, "/addresses", http.StatusOK,
jsonhttptest.WithExpectedJSONResponse(debugapi.AddressesResponse{ jsonhttptest.WithExpectedJSONResponse(debugapi.AddressesResponse{
Overlay: overlay, Overlay: &overlay,
Underlay: addresses, Underlay: addresses,
Ethereum: ethereumAddress, Ethereum: ethereumAddress,
PublicKey: hex.EncodeToString(crypto.EncodeSecp256k1PublicKey(&privateKey.PublicKey)), PublicKey: hex.EncodeToString(crypto.EncodeSecp256k1PublicKey(&privateKey.PublicKey)),
......
...@@ -10,6 +10,7 @@ import ( ...@@ -10,6 +10,7 @@ import (
"net/http" "net/http"
"testing" "testing"
"github.com/ethereum/go-ethereum/common"
"github.com/ethersphere/bee/pkg/bzz" "github.com/ethersphere/bee/pkg/bzz"
"github.com/ethersphere/bee/pkg/crypto" "github.com/ethersphere/bee/pkg/crypto"
"github.com/ethersphere/bee/pkg/debugapi" "github.com/ethersphere/bee/pkg/debugapi"
...@@ -31,7 +32,9 @@ func TestConnect(t *testing.T) { ...@@ -31,7 +32,9 @@ func TestConnect(t *testing.T) {
t.Fatal(err) t.Fatal(err)
} }
overlay, err := crypto.NewOverlayAddress(privateKey.PublicKey, 0) block := common.HexToHash("0x1").Bytes()
overlay, err := crypto.NewOverlayAddress(privateKey.PublicKey, 0, block)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
...@@ -40,7 +43,7 @@ func TestConnect(t *testing.T) { ...@@ -40,7 +43,7 @@ func TestConnect(t *testing.T) {
t.Fatal(err) t.Fatal(err)
} }
bzzAddress, err := bzz.NewAddress(crypto.NewDefaultSigner(privateKey), underlama, overlay, 0) bzzAddress, err := bzz.NewAddress(crypto.NewDefaultSigner(privateKey), underlama, overlay, 0, nil)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
......
...@@ -24,6 +24,7 @@ import ( ...@@ -24,6 +24,7 @@ import (
"github.com/ethersphere/bee/pkg/p2p" "github.com/ethersphere/bee/pkg/p2p"
"github.com/ethersphere/bee/pkg/p2p/protobuf" "github.com/ethersphere/bee/pkg/p2p/protobuf"
"github.com/ethersphere/bee/pkg/swarm" "github.com/ethersphere/bee/pkg/swarm"
ma "github.com/multiformats/go-multiaddr"
"golang.org/x/time/rate" "golang.org/x/time/rate"
) )
...@@ -112,7 +113,9 @@ func (s *Service) sendPeers(ctx context.Context, peer swarm.Address, peers []swa ...@@ -112,7 +113,9 @@ func (s *Service) sendPeers(ctx context.Context, peer swarm.Address, peers []swa
if err != nil { if err != nil {
_ = stream.Reset() _ = stream.Reset()
} else { } else {
_ = stream.FullClose() // added this because Recorder (unit test) emits an unnecessary EOF when Close is called
time.Sleep(time.Millisecond * 50)
_ = stream.Close()
} }
}() }()
w, _ := protobuf.NewWriterAndReader(stream) w, _ := protobuf.NewWriterAndReader(stream)
...@@ -128,9 +131,10 @@ func (s *Service) sendPeers(ctx context.Context, peer swarm.Address, peers []swa ...@@ -128,9 +131,10 @@ func (s *Service) sendPeers(ctx context.Context, peer swarm.Address, peers []swa
} }
peersRequest.Peers = append(peersRequest.Peers, &pb.BzzAddress{ peersRequest.Peers = append(peersRequest.Peers, &pb.BzzAddress{
Overlay: addr.Overlay.Bytes(), Overlay: addr.Overlay.Bytes(),
Underlay: addr.Underlay.Bytes(), Underlay: addr.Underlay.Bytes(),
Signature: addr.Signature, Signature: addr.Signature,
Transaction: addr.Transaction,
}) })
} }
...@@ -166,13 +170,21 @@ func (s *Service) peersHandler(ctx context.Context, peer p2p.Peer, stream p2p.St ...@@ -166,13 +170,21 @@ func (s *Service) peersHandler(ctx context.Context, peer p2p.Peer, stream p2p.St
var peers []swarm.Address var peers []swarm.Address
for _, newPeer := range peersReq.Peers { for _, newPeer := range peersReq.Peers {
bzzAddress, err := bzz.ParseAddress(newPeer.Underlay, newPeer.Overlay, newPeer.Signature, s.networkID)
multiUnderlay, err := ma.NewMultiaddrBytes(newPeer.Underlay)
if err != nil { if err != nil {
s.logger.Warningf("skipping peer in response %s: %v", newPeer.String(), err) s.logger.Errorf("hive: multi address underlay err: %v", err)
continue continue
} }
err = s.addressBook.Put(bzzAddress.Overlay, *bzzAddress) bzzAddress := bzz.Address{
Overlay: swarm.NewAddress(newPeer.Overlay),
Underlay: multiUnderlay,
Signature: newPeer.Signature,
Transaction: newPeer.Transaction,
}
err = s.addressBook.Put(bzzAddress.Overlay, bzzAddress)
if err != nil { if err != nil {
s.logger.Warningf("skipping peer in response %s: %v", newPeer.String(), err) s.logger.Warningf("skipping peer in response %s: %v", newPeer.String(), err)
continue continue
...@@ -193,7 +205,7 @@ func (s *Service) rateLimitPeer(peer swarm.Address, count int) error { ...@@ -193,7 +205,7 @@ func (s *Service) rateLimitPeer(peer swarm.Address, count int) error {
s.limiterLock.Lock() s.limiterLock.Lock()
defer s.limiterLock.Unlock() defer s.limiterLock.Unlock()
addr := peer.String() addr := peer.ByteString()
limiter, ok := s.limiter[addr] limiter, ok := s.limiter[addr]
if !ok { if !ok {
......
...@@ -16,6 +16,7 @@ import ( ...@@ -16,6 +16,7 @@ import (
"testing" "testing"
"time" "time"
"github.com/ethereum/go-ethereum/common"
ma "github.com/multiformats/go-multiaddr" ma "github.com/multiformats/go-multiaddr"
ab "github.com/ethersphere/bee/pkg/addressbook" ab "github.com/ethersphere/bee/pkg/addressbook"
...@@ -31,6 +32,11 @@ import ( ...@@ -31,6 +32,11 @@ import (
"github.com/ethersphere/bee/pkg/swarm/test" "github.com/ethersphere/bee/pkg/swarm/test"
) )
var (
tx = common.HexToHash("0x2").Bytes()
block = common.HexToHash("0x1").Bytes()
)
func TestHandlerRateLimit(t *testing.T) { func TestHandlerRateLimit(t *testing.T) {
logger := logging.New(ioutil.Discard, 0) logger := logging.New(ioutil.Discard, 0)
...@@ -63,11 +69,11 @@ func TestHandlerRateLimit(t *testing.T) { ...@@ -63,11 +69,11 @@ func TestHandlerRateLimit(t *testing.T) {
t.Fatal(err) t.Fatal(err)
} }
signer := crypto.NewDefaultSigner(pk) signer := crypto.NewDefaultSigner(pk)
overlay, err := crypto.NewOverlayAddress(pk.PublicKey, networkID) overlay, err := crypto.NewOverlayAddress(pk.PublicKey, networkID, block)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
bzzAddr, err := bzz.NewAddress(signer, underlay, overlay, networkID) bzzAddr, err := bzz.NewAddress(signer, underlay, overlay, networkID, tx)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
...@@ -86,7 +92,6 @@ func TestHandlerRateLimit(t *testing.T) { ...@@ -86,7 +92,6 @@ func TestHandlerRateLimit(t *testing.T) {
t.Fatal(err) t.Fatal(err)
} }
// // get a record for this stream
rec, err := serverRecorder.Records(serverAddress, "hive", "1.0.0", "peers") rec, err := serverRecorder.Records(serverAddress, "hive", "1.0.0", "peers")
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
...@@ -125,11 +130,11 @@ func TestBroadcastPeers(t *testing.T) { ...@@ -125,11 +130,11 @@ func TestBroadcastPeers(t *testing.T) {
t.Fatal(err) t.Fatal(err)
} }
signer := crypto.NewDefaultSigner(pk) signer := crypto.NewDefaultSigner(pk)
overlay, err := crypto.NewOverlayAddress(pk.PublicKey, networkID) overlay, err := crypto.NewOverlayAddress(pk.PublicKey, networkID, block)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
bzzAddr, err := bzz.NewAddress(signer, underlay, overlay, networkID) bzzAddr, err := bzz.NewAddress(signer, underlay, overlay, networkID, tx)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
...@@ -142,9 +147,10 @@ func TestBroadcastPeers(t *testing.T) { ...@@ -142,9 +147,10 @@ func TestBroadcastPeers(t *testing.T) {
} }
wantMsgs[i/hive.MaxBatchSize].Peers = append(wantMsgs[i/hive.MaxBatchSize].Peers, &pb.BzzAddress{ wantMsgs[i/hive.MaxBatchSize].Peers = append(wantMsgs[i/hive.MaxBatchSize].Peers, &pb.BzzAddress{
Overlay: bzzAddresses[i].Overlay.Bytes(), Overlay: bzzAddresses[i].Overlay.Bytes(),
Underlay: bzzAddresses[i].Underlay.Bytes(), Underlay: bzzAddresses[i].Underlay.Bytes(),
Signature: bzzAddresses[i].Signature, Signature: bzzAddresses[i].Signature,
Transaction: tx,
}) })
} }
......
...@@ -67,9 +67,10 @@ func (m *Peers) GetPeers() []*BzzAddress { ...@@ -67,9 +67,10 @@ func (m *Peers) GetPeers() []*BzzAddress {
} }
type BzzAddress struct { type BzzAddress struct {
Underlay []byte `protobuf:"bytes,1,opt,name=Underlay,proto3" json:"Underlay,omitempty"` Underlay []byte `protobuf:"bytes,1,opt,name=Underlay,proto3" json:"Underlay,omitempty"`
Signature []byte `protobuf:"bytes,2,opt,name=Signature,proto3" json:"Signature,omitempty"` Signature []byte `protobuf:"bytes,2,opt,name=Signature,proto3" json:"Signature,omitempty"`
Overlay []byte `protobuf:"bytes,3,opt,name=Overlay,proto3" json:"Overlay,omitempty"` Overlay []byte `protobuf:"bytes,3,opt,name=Overlay,proto3" json:"Overlay,omitempty"`
Transaction []byte `protobuf:"bytes,4,opt,name=Transaction,proto3" json:"Transaction,omitempty"`
} }
func (m *BzzAddress) Reset() { *m = BzzAddress{} } func (m *BzzAddress) Reset() { *m = BzzAddress{} }
...@@ -126,6 +127,13 @@ func (m *BzzAddress) GetOverlay() []byte { ...@@ -126,6 +127,13 @@ func (m *BzzAddress) GetOverlay() []byte {
return nil return nil
} }
func (m *BzzAddress) GetTransaction() []byte {
if m != nil {
return m.Transaction
}
return nil
}
func init() { func init() {
proto.RegisterType((*Peers)(nil), "hive.Peers") proto.RegisterType((*Peers)(nil), "hive.Peers")
proto.RegisterType((*BzzAddress)(nil), "hive.BzzAddress") proto.RegisterType((*BzzAddress)(nil), "hive.BzzAddress")
...@@ -134,18 +142,20 @@ func init() { ...@@ -134,18 +142,20 @@ func init() {
func init() { proto.RegisterFile("hive.proto", fileDescriptor_d635d1ead41ba02c) } func init() { proto.RegisterFile("hive.proto", fileDescriptor_d635d1ead41ba02c) }
var fileDescriptor_d635d1ead41ba02c = []byte{ var fileDescriptor_d635d1ead41ba02c = []byte{
// 174 bytes of a gzipped FileDescriptorProto // 196 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xe2, 0xca, 0xc8, 0x2c, 0x4b, 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xe2, 0xca, 0xc8, 0x2c, 0x4b,
0xd5, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x62, 0x01, 0xb1, 0x95, 0xf4, 0xb9, 0x58, 0x03, 0x52, 0xd5, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x62, 0x01, 0xb1, 0x95, 0xf4, 0xb9, 0x58, 0x03, 0x52,
0x53, 0x8b, 0x8a, 0x85, 0xd4, 0xb8, 0x58, 0x0b, 0x40, 0x0c, 0x09, 0x46, 0x05, 0x66, 0x0d, 0x6e, 0x53, 0x8b, 0x8a, 0x85, 0xd4, 0xb8, 0x58, 0x0b, 0x40, 0x0c, 0x09, 0x46, 0x05, 0x66, 0x0d, 0x6e,
0x23, 0x01, 0x3d, 0xb0, 0x52, 0xa7, 0xaa, 0x2a, 0xc7, 0x94, 0x94, 0xa2, 0xd4, 0xe2, 0xe2, 0x20, 0x23, 0x01, 0x3d, 0xb0, 0x52, 0xa7, 0xaa, 0x2a, 0xc7, 0x94, 0x94, 0xa2, 0xd4, 0xe2, 0xe2, 0x20,
0x88, 0xb4, 0x52, 0x02, 0x17, 0x17, 0x42, 0x50, 0x48, 0x8a, 0x8b, 0x23, 0x34, 0x2f, 0x25, 0xb5, 0x88, 0xb4, 0x52, 0x13, 0x23, 0x17, 0x17, 0x42, 0x54, 0x48, 0x8a, 0x8b, 0x23, 0x34, 0x2f, 0x25,
0x28, 0x27, 0xb1, 0x52, 0x82, 0x51, 0x81, 0x51, 0x83, 0x27, 0x08, 0xce, 0x17, 0x92, 0xe1, 0xe2, 0xb5, 0x28, 0x27, 0xb1, 0x52, 0x82, 0x51, 0x81, 0x51, 0x83, 0x27, 0x08, 0xce, 0x17, 0x92, 0xe1,
0x0c, 0xce, 0x4c, 0xcf, 0x4b, 0x2c, 0x29, 0x2d, 0x4a, 0x95, 0x60, 0x02, 0x4b, 0x22, 0x04, 0x84, 0xe2, 0x0c, 0xce, 0x4c, 0xcf, 0x4b, 0x2c, 0x29, 0x2d, 0x4a, 0x95, 0x60, 0x02, 0x4b, 0x22, 0x04,
0x24, 0xb8, 0xd8, 0xfd, 0xcb, 0x20, 0x1a, 0x99, 0xc1, 0x72, 0x30, 0xae, 0x93, 0xcc, 0x89, 0x47, 0x84, 0x24, 0xb8, 0xd8, 0xfd, 0xcb, 0x20, 0x1a, 0x99, 0xc1, 0x72, 0x30, 0xae, 0x90, 0x02, 0x17,
0x72, 0x8c, 0x17, 0x1e, 0xc9, 0x31, 0x3e, 0x78, 0x24, 0xc7, 0x38, 0xe1, 0xb1, 0x1c, 0xc3, 0x85, 0x77, 0x48, 0x51, 0x62, 0x5e, 0x71, 0x62, 0x72, 0x49, 0x66, 0x7e, 0x9e, 0x04, 0x0b, 0x58, 0x16,
0xc7, 0x72, 0x0c, 0x37, 0x1e, 0xcb, 0x31, 0x44, 0x31, 0x15, 0x24, 0x25, 0xb1, 0x81, 0x5d, 0x6f, 0x59, 0xc8, 0x49, 0xe6, 0xc4, 0x23, 0x39, 0xc6, 0x0b, 0x8f, 0xe4, 0x18, 0x1f, 0x3c, 0x92, 0x63,
0x0c, 0x08, 0x00, 0x00, 0xff, 0xff, 0x2e, 0x11, 0xc0, 0xe9, 0xcb, 0x00, 0x00, 0x00, 0x9c, 0xf0, 0x58, 0x8e, 0xe1, 0xc2, 0x63, 0x39, 0x86, 0x1b, 0x8f, 0xe5, 0x18, 0xa2, 0x98, 0x0a,
0x92, 0x92, 0xd8, 0xc0, 0x1e, 0x34, 0x06, 0x04, 0x00, 0x00, 0xff, 0xff, 0xe0, 0x0a, 0xbb, 0x89,
0xee, 0x00, 0x00, 0x00,
} }
func (m *Peers) Marshal() (dAtA []byte, err error) { func (m *Peers) Marshal() (dAtA []byte, err error) {
...@@ -205,6 +215,13 @@ func (m *BzzAddress) MarshalToSizedBuffer(dAtA []byte) (int, error) { ...@@ -205,6 +215,13 @@ func (m *BzzAddress) MarshalToSizedBuffer(dAtA []byte) (int, error) {
_ = i _ = i
var l int var l int
_ = l _ = l
if len(m.Transaction) > 0 {
i -= len(m.Transaction)
copy(dAtA[i:], m.Transaction)
i = encodeVarintHive(dAtA, i, uint64(len(m.Transaction)))
i--
dAtA[i] = 0x22
}
if len(m.Overlay) > 0 { if len(m.Overlay) > 0 {
i -= len(m.Overlay) i -= len(m.Overlay)
copy(dAtA[i:], m.Overlay) copy(dAtA[i:], m.Overlay)
...@@ -273,6 +290,10 @@ func (m *BzzAddress) Size() (n int) { ...@@ -273,6 +290,10 @@ func (m *BzzAddress) Size() (n int) {
if l > 0 { if l > 0 {
n += 1 + l + sovHive(uint64(l)) n += 1 + l + sovHive(uint64(l))
} }
l = len(m.Transaction)
if l > 0 {
n += 1 + l + sovHive(uint64(l))
}
return n return n
} }
...@@ -500,6 +521,40 @@ func (m *BzzAddress) Unmarshal(dAtA []byte) error { ...@@ -500,6 +521,40 @@ func (m *BzzAddress) Unmarshal(dAtA []byte) error {
m.Overlay = []byte{} m.Overlay = []byte{}
} }
iNdEx = postIndex iNdEx = postIndex
case 4:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Transaction", wireType)
}
var byteLen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowHive
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
byteLen |= int(b&0x7F) << shift
if b < 0x80 {
break
}
}
if byteLen < 0 {
return ErrInvalidLengthHive
}
postIndex := iNdEx + byteLen
if postIndex < 0 {
return ErrInvalidLengthHive
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.Transaction = append(m.Transaction[:0], dAtA[iNdEx:postIndex]...)
if m.Transaction == nil {
m.Transaction = []byte{}
}
iNdEx = postIndex
default: default:
iNdEx = preIndex iNdEx = preIndex
skippy, err := skipHive(dAtA[iNdEx:]) skippy, err := skipHive(dAtA[iNdEx:])
......
...@@ -16,4 +16,5 @@ message BzzAddress { ...@@ -16,4 +16,5 @@ message BzzAddress {
bytes Underlay = 1; bytes Underlay = 1;
bytes Signature = 2; bytes Signature = 2;
bytes Overlay = 3; bytes Overlay = 3;
bytes Transaction = 4;
} }
...@@ -6,9 +6,11 @@ package node ...@@ -6,9 +6,11 @@ package node
import ( import (
"context" "context"
"encoding/hex"
"errors" "errors"
"fmt" "fmt"
"math/big" "math/big"
"strings"
"time" "time"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
...@@ -39,7 +41,7 @@ func InitChain( ...@@ -39,7 +41,7 @@ func InitChain(
stateStore storage.StateStorer, stateStore storage.StateStorer,
endpoint string, endpoint string,
signer crypto.Signer, signer crypto.Signer,
blocktime uint64, pollingInterval time.Duration,
) (*ethclient.Client, common.Address, int64, transaction.Monitor, transaction.Service, error) { ) (*ethclient.Client, common.Address, int64, transaction.Monitor, transaction.Service, error) {
backend, err := ethclient.Dial(endpoint) backend, err := ethclient.Dial(endpoint)
if err != nil { if err != nil {
...@@ -52,7 +54,6 @@ func InitChain( ...@@ -52,7 +54,6 @@ func InitChain(
return nil, common.Address{}, 0, nil, nil, fmt.Errorf("get chain id: %w", err) return nil, common.Address{}, 0, nil, nil, fmt.Errorf("get chain id: %w", err)
} }
pollingInterval := time.Duration(blocktime) * time.Second
overlayEthAddress, err := signer.EthereumAddress() overlayEthAddress, err := signer.EthereumAddress()
if err != nil { if err != nil {
return nil, common.Address{}, 0, nil, nil, fmt.Errorf("eth address: %w", err) return nil, common.Address{}, 0, nil, nil, fmt.Errorf("eth address: %w", err)
...@@ -257,3 +258,65 @@ func InitSwap( ...@@ -257,3 +258,65 @@ func InitSwap(
return swapService, priceOracle, nil return swapService, priceOracle, nil
} }
func GetTxHash(stateStore storage.StateStorer, logger logging.Logger, trxString string) ([]byte, error) {
if trxString != "" {
txHashTrimmed := strings.TrimPrefix(trxString, "0x")
if len(txHashTrimmed) != 64 {
return nil, errors.New("invalid length")
}
txHash, err := hex.DecodeString(txHashTrimmed)
if err != nil {
return nil, err
}
logger.Infof("using the provided transaction hash %x", txHash)
return txHash, nil
}
var txHash common.Hash
key := chequebook.ChequebookDeploymentKey
if err := stateStore.Get(key, &txHash); err != nil {
if errors.Is(err, storage.ErrNotFound) {
return nil, errors.New("chequebook deployment transaction hash not found, please specify the transaction hash manually")
}
return nil, err
}
logger.Infof("using the chequebook transaction hash %x", txHash)
return txHash.Bytes(), nil
}
func GetTxNextBlock(ctx context.Context, logger logging.Logger, backend transaction.Backend, monitor transaction.Monitor, duration time.Duration, trx []byte, blockHash string) ([]byte, error) {
if blockHash != "" {
blockHashTrimmed := strings.TrimPrefix(blockHash, "0x")
if len(blockHashTrimmed) != 64 {
return nil, errors.New("invalid length")
}
blockHash, err := hex.DecodeString(blockHashTrimmed)
if err != nil {
return nil, err
}
logger.Infof("using the provided block hash %x", blockHash)
return blockHash, nil
}
// if not found in statestore, fetch from chain
tx, err := backend.TransactionReceipt(ctx, common.BytesToHash(trx))
if err != nil {
return nil, err
}
block, err := transaction.WaitBlock(ctx, backend, duration, big.NewInt(0).Add(tx.BlockNumber, big.NewInt(1)))
if err != nil {
return nil, err
}
hash := block.Hash()
hashBytes := hash.Bytes()
logger.Infof("using the next block hash from the blockchain %x", hashBytes)
return hashBytes, nil
}
...@@ -10,7 +10,6 @@ package node ...@@ -10,7 +10,6 @@ package node
import ( import (
"context" "context"
"crypto/ecdsa" "crypto/ecdsa"
"encoding/hex"
"errors" "errors"
"fmt" "fmt"
"io" "io"
...@@ -20,7 +19,6 @@ import ( ...@@ -20,7 +19,6 @@ import (
"net/http" "net/http"
"os" "os"
"path/filepath" "path/filepath"
"strings"
"sync" "sync"
"syscall" "syscall"
"time" "time"
...@@ -66,7 +64,6 @@ import ( ...@@ -66,7 +64,6 @@ import (
"github.com/ethersphere/bee/pkg/shed" "github.com/ethersphere/bee/pkg/shed"
"github.com/ethersphere/bee/pkg/steward" "github.com/ethersphere/bee/pkg/steward"
"github.com/ethersphere/bee/pkg/storage" "github.com/ethersphere/bee/pkg/storage"
"github.com/ethersphere/bee/pkg/swarm"
"github.com/ethersphere/bee/pkg/tags" "github.com/ethersphere/bee/pkg/tags"
"github.com/ethersphere/bee/pkg/topology" "github.com/ethersphere/bee/pkg/topology"
"github.com/ethersphere/bee/pkg/topology/kademlia" "github.com/ethersphere/bee/pkg/topology/kademlia"
...@@ -146,6 +143,7 @@ type Options struct { ...@@ -146,6 +143,7 @@ type Options struct {
SwapEnable bool SwapEnable bool
FullNodeMode bool FullNodeMode bool
Transaction string Transaction string
BlockHash string
PostageContractAddress string PostageContractAddress string
PriceOracleAddress string PriceOracleAddress string
BlockTime uint64 BlockTime uint64
...@@ -158,7 +156,7 @@ const ( ...@@ -158,7 +156,7 @@ const (
basePrice = 10000 basePrice = 10000
) )
func NewBee(addr string, swarmAddress swarm.Address, publicKey ecdsa.PublicKey, signer crypto.Signer, networkID uint64, logger logging.Logger, libp2pPrivateKey, pssPrivateKey *ecdsa.PrivateKey, o Options) (b *Bee, err error) { func NewBee(addr string, publicKey *ecdsa.PublicKey, signer crypto.Signer, networkID uint64, logger logging.Logger, libp2pPrivateKey, pssPrivateKey *ecdsa.PrivateKey, o *Options) (b *Bee, err error) {
tracer, tracerCloser, err := tracing.NewTracer(&tracing.Options{ tracer, tracerCloser, err := tracing.NewTracer(&tracing.Options{
Enabled: o.TracingEnabled, Enabled: o.TracingEnabled,
Endpoint: o.TracingEndpoint, Endpoint: o.TracingEndpoint,
...@@ -190,6 +188,14 @@ func NewBee(addr string, swarmAddress swarm.Address, publicKey ecdsa.PublicKey, ...@@ -190,6 +188,14 @@ func NewBee(addr string, swarmAddress swarm.Address, publicKey ecdsa.PublicKey,
tracerCloser: tracerCloser, tracerCloser: tracerCloser,
} }
stateStore, err := InitStateStore(logger, o.DataDir)
if err != nil {
return nil, err
}
b.stateStoreCloser = stateStore
addressbook := addressbook.New(stateStore)
var debugAPIService *debugapi.Service var debugAPIService *debugapi.Service
if o.DebugAPIAddr != "" { if o.DebugAPIAddr != "" {
overlayEthAddress, err := signer.EthereumAddress() overlayEthAddress, err := signer.EthereumAddress()
...@@ -197,7 +203,7 @@ func NewBee(addr string, swarmAddress swarm.Address, publicKey ecdsa.PublicKey, ...@@ -197,7 +203,7 @@ func NewBee(addr string, swarmAddress swarm.Address, publicKey ecdsa.PublicKey,
return nil, fmt.Errorf("eth address: %w", err) return nil, fmt.Errorf("eth address: %w", err)
} }
// set up basic debug api endpoints for debugging and /health endpoint // set up basic debug api endpoints for debugging and /health endpoint
debugAPIService = debugapi.New(swarmAddress, publicKey, pssPrivateKey.PublicKey, overlayEthAddress, logger, tracer, o.CORSAllowedOrigins) debugAPIService = debugapi.New(*publicKey, pssPrivateKey.PublicKey, overlayEthAddress, logger, tracer, o.CORSAllowedOrigins)
debugAPIListener, err := net.Listen("tcp", o.DebugAPIAddr) debugAPIListener, err := net.Listen("tcp", o.DebugAPIAddr)
if err != nil { if err != nil {
...@@ -223,19 +229,6 @@ func NewBee(addr string, swarmAddress swarm.Address, publicKey ecdsa.PublicKey, ...@@ -223,19 +229,6 @@ func NewBee(addr string, swarmAddress swarm.Address, publicKey ecdsa.PublicKey,
b.debugAPIServer = debugAPIServer b.debugAPIServer = debugAPIServer
} }
stateStore, err := InitStateStore(logger, o.DataDir)
if err != nil {
return nil, err
}
b.stateStoreCloser = stateStore
err = CheckOverlayWithStore(swarmAddress, stateStore)
if err != nil {
return nil, err
}
addressbook := addressbook.New(stateStore)
var ( var (
swapBackend *ethclient.Client swapBackend *ethclient.Client
overlayEthAddress common.Address overlayEthAddress common.Address
...@@ -246,6 +239,7 @@ func NewBee(addr string, swarmAddress swarm.Address, publicKey ecdsa.PublicKey, ...@@ -246,6 +239,7 @@ func NewBee(addr string, swarmAddress swarm.Address, publicKey ecdsa.PublicKey,
chequebookService chequebook.Service chequebookService chequebook.Service
chequeStore chequebook.ChequeStore chequeStore chequebook.ChequeStore
cashoutService chequebook.CashoutService cashoutService chequebook.CashoutService
pollingInterval = time.Duration(o.BlockTime) * time.Second
) )
if !o.Standalone { if !o.Standalone {
swapBackend, overlayEthAddress, chainID, transactionMonitor, transactionService, err = InitChain( swapBackend, overlayEthAddress, chainID, transactionMonitor, transactionService, err = InitChain(
...@@ -254,7 +248,7 @@ func NewBee(addr string, swarmAddress swarm.Address, publicKey ecdsa.PublicKey, ...@@ -254,7 +248,7 @@ func NewBee(addr string, swarmAddress swarm.Address, publicKey ecdsa.PublicKey,
stateStore, stateStore,
o.SwapEndpoint, o.SwapEndpoint,
signer, signer,
o.BlockTime, pollingInterval,
) )
if err != nil { if err != nil {
return nil, fmt.Errorf("init chain: %w", err) return nil, fmt.Errorf("init chain: %w", err)
...@@ -308,13 +302,35 @@ func NewBee(addr string, swarmAddress swarm.Address, publicKey ecdsa.PublicKey, ...@@ -308,13 +302,35 @@ func NewBee(addr string, swarmAddress swarm.Address, publicKey ecdsa.PublicKey,
) )
} }
lightNodes := lightnode.NewContainer(swarmAddress) pubKey, _ := signer.PublicKey()
if err != nil {
return nil, err
}
var (
blockHash []byte
txHash []byte
)
txHash, err := getTxHash(stateStore, logger, o) txHash, err = GetTxHash(stateStore, logger, o.Transaction)
if err != nil { if err != nil {
return nil, fmt.Errorf("invalid transaction hash: %w", err) return nil, fmt.Errorf("invalid transaction hash: %w", err)
} }
blockHash, err = GetTxNextBlock(p2pCtx, logger, swapBackend, transactionMonitor, pollingInterval, txHash, o.BlockHash)
if err != nil {
return nil, fmt.Errorf("invalid block hash: %w", err)
}
swarmAddress, err := crypto.NewOverlayAddress(*pubKey, networkID, blockHash)
err = CheckOverlayWithStore(swarmAddress, stateStore)
if err != nil {
return nil, err
}
lightNodes := lightnode.NewContainer(swarmAddress)
senderMatcher := transaction.NewMatcher(swapBackend, types.NewEIP155Signer(big.NewInt(chainID))) senderMatcher := transaction.NewMatcher(swapBackend, types.NewEIP155Signer(big.NewInt(chainID)))
p2ps, err := libp2p.New(p2pCtx, signer, networkID, swarmAddress, addr, addressbook, stateStore, lightNodes, senderMatcher, logger, tracer, libp2p.Options{ p2ps, err := libp2p.New(p2pCtx, signer, networkID, swarmAddress, addr, addressbook, stateStore, lightNodes, senderMatcher, logger, tracer, libp2p.Options{
...@@ -583,7 +599,7 @@ func NewBee(addr string, swarmAddress swarm.Address, publicKey ecdsa.PublicKey, ...@@ -583,7 +599,7 @@ func NewBee(addr string, swarmAddress swarm.Address, publicKey ecdsa.PublicKey,
pinningService := pinning.NewService(storer, stateStore, traversalService) pinningService := pinning.NewService(storer, stateStore, traversalService)
pushSyncProtocol := pushsync.New(swarmAddress, p2ps, storer, kad, tagService, o.FullNodeMode, pssService.TryUnwrap, validStamp, logger, acc, pricer, signer, tracer, warmupTime) pushSyncProtocol := pushsync.New(swarmAddress, blockHash, p2ps, storer, kad, tagService, o.FullNodeMode, pssService.TryUnwrap, validStamp, logger, acc, pricer, signer, tracer, warmupTime)
// set the pushSyncer in the PSS // set the pushSyncer in the PSS
pssService.SetPushSyncer(pushSyncProtocol) pssService.SetPushSyncer(pushSyncProtocol)
...@@ -719,7 +735,7 @@ func NewBee(addr string, swarmAddress swarm.Address, publicKey ecdsa.PublicKey, ...@@ -719,7 +735,7 @@ func NewBee(addr string, swarmAddress swarm.Address, publicKey ecdsa.PublicKey,
} }
// inject dependencies and configure full debug api http path routes // inject dependencies and configure full debug api http path routes
debugAPIService.Configure(p2ps, pingPong, kad, lightNodes, storer, tagService, acc, pseudosettleService, o.SwapEnable, swapService, chequebookService, batchStore, transactionService) debugAPIService.Configure(swarmAddress, p2ps, pingPong, kad, lightNodes, storer, tagService, acc, pseudosettleService, o.SwapEnable, swapService, chequebookService, batchStore, transactionService)
} }
if err := kad.Start(p2pCtx); err != nil { if err := kad.Start(p2pCtx); err != nil {
...@@ -849,37 +865,6 @@ func (b *Bee) Shutdown(ctx context.Context) error { ...@@ -849,37 +865,6 @@ func (b *Bee) Shutdown(ctx context.Context) error {
return mErr return mErr
} }
func getTxHash(stateStore storage.StateStorer, logger logging.Logger, o Options) ([]byte, error) {
if o.Standalone {
return nil, nil // in standalone mode tx hash is not used
}
if o.Transaction != "" {
txHashTrimmed := strings.TrimPrefix(o.Transaction, "0x")
if len(txHashTrimmed) != 64 {
return nil, errors.New("invalid length")
}
txHash, err := hex.DecodeString(txHashTrimmed)
if err != nil {
return nil, err
}
logger.Infof("using the provided transaction hash %x", txHash)
return txHash, nil
}
var txHash common.Hash
key := chequebook.ChequebookDeploymentKey
if err := stateStore.Get(key, &txHash); err != nil {
if errors.Is(err, storage.ErrNotFound) {
return nil, errors.New("chequebook deployment transaction hash not found. Please specify the transaction hash manually.")
}
return nil, err
}
logger.Infof("using the chequebook transaction hash %x", txHash)
return txHash.Bytes(), nil
}
// pidKiller is used to issue a forced shut down of the node from sub modules. The issue with using the // pidKiller is used to issue a forced shut down of the node from sub modules. The issue with using the
// node's Shutdown method is that it only shuts down the node and does not exit the start process // node's Shutdown method is that it only shuts down the node and does not exit the start process
// which is waiting on the os.Signals. This is not desirable, but currently bee node cannot handle // which is waiting on the os.Signals. This is not desirable, but currently bee node cannot handle
......
...@@ -50,9 +50,6 @@ var ( ...@@ -50,9 +50,6 @@ var (
// ErrInvalidSyn is returned if observable address in ack is not a valid.. // ErrInvalidSyn is returned if observable address in ack is not a valid..
ErrInvalidSyn = errors.New("invalid syn") ErrInvalidSyn = errors.New("invalid syn")
// ErrAddressNotFound is returned if observable address in ack is not a valid..
ErrAddressNotFound = errors.New("address not found")
// ErrWelcomeMessageLength is returned if the welcome message is longer than the maximum length // ErrWelcomeMessageLength is returned if the welcome message is longer than the maximum length
ErrWelcomeMessageLength = fmt.Errorf("handshake welcome message longer than maximum of %d characters", MaxWelcomeMessageLength) ErrWelcomeMessageLength = fmt.Errorf("handshake welcome message longer than maximum of %d characters", MaxWelcomeMessageLength)
) )
...@@ -63,7 +60,7 @@ type AdvertisableAddressResolver interface { ...@@ -63,7 +60,7 @@ type AdvertisableAddressResolver interface {
} }
type SenderMatcher interface { type SenderMatcher interface {
Matches(ctx context.Context, tx []byte, networkID uint64, senderOverlay swarm.Address) (bool, error) Matches(ctx context.Context, tx []byte, networkID uint64, senderOverlay swarm.Address) ([]byte, error)
} }
// Service can perform initiate or handle a handshake between peers. // Service can perform initiate or handle a handshake between peers.
...@@ -147,11 +144,6 @@ func (s *Service) Handshake(ctx context.Context, stream p2p.Stream, peerMultiadd ...@@ -147,11 +144,6 @@ func (s *Service) Handshake(ctx context.Context, stream p2p.Stream, peerMultiadd
return nil, fmt.Errorf("read synack message: %w", err) return nil, fmt.Errorf("read synack message: %w", err)
} }
remoteBzzAddress, err := s.parseCheckAck(resp.Ack)
if err != nil {
return nil, err
}
observedUnderlay, err := ma.NewMultiaddrBytes(resp.Syn.ObservedUnderlay) observedUnderlay, err := ma.NewMultiaddrBytes(resp.Syn.ObservedUnderlay)
if err != nil { if err != nil {
return nil, ErrInvalidSyn return nil, ErrInvalidSyn
...@@ -162,7 +154,7 @@ func (s *Service) Handshake(ctx context.Context, stream p2p.Stream, peerMultiadd ...@@ -162,7 +154,7 @@ func (s *Service) Handshake(ctx context.Context, stream p2p.Stream, peerMultiadd
return nil, err return nil, err
} }
bzzAddress, err := bzz.NewAddress(s.signer, advertisableUnderlay, s.overlay, s.networkID) bzzAddress, err := bzz.NewAddress(s.signer, advertisableUnderlay, s.overlay, s.networkID, s.transaction)
if err != nil { if err != nil {
return nil, err return nil, err
} }
...@@ -172,6 +164,18 @@ func (s *Service) Handshake(ctx context.Context, stream p2p.Stream, peerMultiadd ...@@ -172,6 +164,18 @@ func (s *Service) Handshake(ctx context.Context, stream p2p.Stream, peerMultiadd
return nil, err return nil, err
} }
overlay := swarm.NewAddress(resp.Ack.Address.Overlay)
blockHash, err := s.senderMatcher.Matches(ctx, resp.Ack.Transaction, s.networkID, overlay)
if err != nil {
return nil, fmt.Errorf("overlay %v verification failed: %w", overlay, err)
}
remoteBzzAddress, err := s.parseCheckAck(resp.Ack, blockHash)
if err != nil {
return nil, err
}
// Synced read: // Synced read:
welcomeMessage := s.GetWelcomeMessage() welcomeMessage := s.GetWelcomeMessage()
if err := w.WriteMsgWithContext(ctx, &pb.Ack{ if err := w.WriteMsgWithContext(ctx, &pb.Ack{
...@@ -238,7 +242,7 @@ func (s *Service) Handle(ctx context.Context, stream p2p.Stream, remoteMultiaddr ...@@ -238,7 +242,7 @@ func (s *Service) Handle(ctx context.Context, stream p2p.Stream, remoteMultiaddr
return nil, err return nil, err
} }
bzzAddress, err := bzz.NewAddress(s.signer, advertisableUnderlay, s.overlay, s.networkID) bzzAddress, err := bzz.NewAddress(s.signer, advertisableUnderlay, s.overlay, s.networkID, s.transaction)
if err != nil { if err != nil {
return nil, err return nil, err
} }
...@@ -274,23 +278,21 @@ func (s *Service) Handle(ctx context.Context, stream p2p.Stream, remoteMultiaddr ...@@ -274,23 +278,21 @@ func (s *Service) Handle(ctx context.Context, stream p2p.Stream, remoteMultiaddr
return nil, fmt.Errorf("read ack message: %w", err) return nil, fmt.Errorf("read ack message: %w", err)
} }
remoteBzzAddress, err := s.parseCheckAck(&ack) overlay := swarm.NewAddress(ack.Address.Overlay)
if err != nil {
return nil, err
}
s.logger.Tracef("handshake finished for peer (inbound) %s", remoteBzzAddress.Overlay.String()) blockHash, err := s.senderMatcher.Matches(ctx, ack.Transaction, s.networkID, overlay)
if len(ack.WelcomeMessage) > 0 { if err != nil {
s.logger.Infof("greeting \"%s\" from peer: %s", ack.WelcomeMessage, remoteBzzAddress.Overlay.String()) return nil, fmt.Errorf("overlay %v verification failed: %w", overlay, err)
} }
matchesSender, err := s.senderMatcher.Matches(ctx, ack.Transaction, s.networkID, remoteBzzAddress.Overlay) remoteBzzAddress, err := s.parseCheckAck(&ack, blockHash)
if err != nil { if err != nil {
return nil, err return nil, err
} }
if !matchesSender { s.logger.Tracef("handshake finished for peer (inbound) %s", remoteBzzAddress.Overlay.String())
return nil, fmt.Errorf("given address is not registered on Ethereum: %v: %w", remoteBzzAddress.Overlay, ErrAddressNotFound) if len(ack.WelcomeMessage) > 0 {
s.logger.Infof("greeting \"%s\" from peer: %s", ack.WelcomeMessage, remoteBzzAddress.Overlay.String())
} }
return &Info{ return &Info{
...@@ -324,12 +326,12 @@ func buildFullMA(addr ma.Multiaddr, peerID libp2ppeer.ID) (ma.Multiaddr, error) ...@@ -324,12 +326,12 @@ func buildFullMA(addr ma.Multiaddr, peerID libp2ppeer.ID) (ma.Multiaddr, error)
return ma.NewMultiaddr(fmt.Sprintf("%s/p2p/%s", addr.String(), peerID.Pretty())) return ma.NewMultiaddr(fmt.Sprintf("%s/p2p/%s", addr.String(), peerID.Pretty()))
} }
func (s *Service) parseCheckAck(ack *pb.Ack) (*bzz.Address, error) { func (s *Service) parseCheckAck(ack *pb.Ack, blockHash []byte) (*bzz.Address, error) {
if ack.NetworkID != s.networkID { if ack.NetworkID != s.networkID {
return nil, ErrNetworkIDIncompatible return nil, ErrNetworkIDIncompatible
} }
bzzAddress, err := bzz.ParseAddress(ack.Address.Underlay, ack.Address.Overlay, ack.Address.Signature, s.networkID) bzzAddress, err := bzz.ParseAddress(ack.Address.Underlay, ack.Address.Overlay, ack.Address.Signature, ack.Transaction, blockHash, s.networkID)
if err != nil { if err != nil {
return nil, ErrInvalidAck return nil, ErrInvalidAck
} }
......
...@@ -12,6 +12,7 @@ import ( ...@@ -12,6 +12,7 @@ import (
"io/ioutil" "io/ioutil"
"testing" "testing"
"github.com/ethereum/go-ethereum/common"
"github.com/ethersphere/bee/pkg/bzz" "github.com/ethersphere/bee/pkg/bzz"
"github.com/ethersphere/bee/pkg/crypto" "github.com/ethersphere/bee/pkg/crypto"
"github.com/ethersphere/bee/pkg/logging" "github.com/ethersphere/bee/pkg/logging"
...@@ -63,21 +64,24 @@ func TestHandshake(t *testing.T) { ...@@ -63,21 +64,24 @@ func TestHandshake(t *testing.T) {
t.Fatal(err) t.Fatal(err)
} }
trxHash := common.HexToHash("0x1").Bytes()
blockhash := common.HexToHash("0x2").Bytes()
signer1 := crypto.NewDefaultSigner(privateKey1) signer1 := crypto.NewDefaultSigner(privateKey1)
signer2 := crypto.NewDefaultSigner(privateKey2) signer2 := crypto.NewDefaultSigner(privateKey2)
addr, err := crypto.NewOverlayAddress(privateKey1.PublicKey, networkID) addr, err := crypto.NewOverlayAddress(privateKey1.PublicKey, networkID, blockhash)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
node1BzzAddress, err := bzz.NewAddress(signer1, node1ma, addr, networkID) node1BzzAddress, err := bzz.NewAddress(signer1, node1ma, addr, networkID, trxHash)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
addr2, err := crypto.NewOverlayAddress(privateKey2.PublicKey, networkID) addr2, err := crypto.NewOverlayAddress(privateKey2.PublicKey, networkID, blockhash)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
node2BzzAddress, err := bzz.NewAddress(signer2, node2ma, addr2, networkID) node2BzzAddress, err := bzz.NewAddress(signer2, node2ma, addr2, networkID, trxHash)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
...@@ -92,9 +96,10 @@ func TestHandshake(t *testing.T) { ...@@ -92,9 +96,10 @@ func TestHandshake(t *testing.T) {
} }
aaddresser := &AdvertisableAddresserMock{} aaddresser := &AdvertisableAddresserMock{}
senderMatcher := &MockSenderMatcher{v: true}
handshakeService, err := handshake.New(signer1, aaddresser, senderMatcher, node1Info.BzzAddress.Overlay, networkID, true, nil, testWelcomeMessage, logger) senderMatcher := &MockSenderMatcher{v: true, blockHash: blockhash}
handshakeService, err := handshake.New(signer1, aaddresser, senderMatcher, node1Info.BzzAddress.Overlay, networkID, true, trxHash, testWelcomeMessage, logger)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
...@@ -118,6 +123,7 @@ func TestHandshake(t *testing.T) { ...@@ -118,6 +123,7 @@ func TestHandshake(t *testing.T) {
}, },
NetworkID: networkID, NetworkID: networkID,
FullNode: true, FullNode: true,
Transaction: trxHash,
WelcomeMessage: testWelcomeMessage, WelcomeMessage: testWelcomeMessage,
}, },
}); err != nil { }); err != nil {
...@@ -370,7 +376,7 @@ func TestHandshake(t *testing.T) { ...@@ -370,7 +376,7 @@ func TestHandshake(t *testing.T) {
}) })
t.Run("Handle - OK", func(t *testing.T) { t.Run("Handle - OK", func(t *testing.T) {
handshakeService, err := handshake.New(signer1, aaddresser, senderMatcher, node1Info.BzzAddress.Overlay, networkID, true, nil, "", logger) handshakeService, err := handshake.New(signer1, aaddresser, senderMatcher, node1Info.BzzAddress.Overlay, networkID, true, trxHash, "", logger)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
...@@ -392,8 +398,9 @@ func TestHandshake(t *testing.T) { ...@@ -392,8 +398,9 @@ func TestHandshake(t *testing.T) {
Overlay: node2BzzAddress.Overlay.Bytes(), Overlay: node2BzzAddress.Overlay.Bytes(),
Signature: node2BzzAddress.Signature, Signature: node2BzzAddress.Signature,
}, },
NetworkID: networkID, NetworkID: networkID,
FullNode: true, Transaction: trxHash,
FullNode: true,
}); err != nil { }); err != nil {
t.Fatal(err) t.Fatal(err)
} }
...@@ -415,7 +422,7 @@ func TestHandshake(t *testing.T) { ...@@ -415,7 +422,7 @@ func TestHandshake(t *testing.T) {
t.Fatalf("got bad syn") t.Fatalf("got bad syn")
} }
bzzAddress, err := bzz.ParseAddress(got.Ack.Address.Underlay, got.Ack.Address.Overlay, got.Ack.Address.Signature, got.Ack.NetworkID) bzzAddress, err := bzz.ParseAddress(got.Ack.Address.Underlay, got.Ack.Address.Overlay, got.Ack.Address.Signature, got.Ack.Transaction, blockhash, got.Ack.NetworkID)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
...@@ -541,7 +548,7 @@ func TestHandshake(t *testing.T) { ...@@ -541,7 +548,7 @@ func TestHandshake(t *testing.T) {
}) })
t.Run("Handle - duplicate handshake", func(t *testing.T) { t.Run("Handle - duplicate handshake", func(t *testing.T) {
handshakeService, err := handshake.New(signer1, aaddresser, senderMatcher, node1Info.BzzAddress.Overlay, networkID, true, nil, "", logger) handshakeService, err := handshake.New(signer1, aaddresser, senderMatcher, node1Info.BzzAddress.Overlay, networkID, true, trxHash, "", logger)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
...@@ -563,8 +570,9 @@ func TestHandshake(t *testing.T) { ...@@ -563,8 +570,9 @@ func TestHandshake(t *testing.T) {
Overlay: node2BzzAddress.Overlay.Bytes(), Overlay: node2BzzAddress.Overlay.Bytes(),
Signature: node2BzzAddress.Signature, Signature: node2BzzAddress.Signature,
}, },
NetworkID: networkID, NetworkID: networkID,
FullNode: true, Transaction: trxHash,
FullNode: true,
}); err != nil { }); err != nil {
t.Fatal(err) t.Fatal(err)
} }
...@@ -585,8 +593,7 @@ func TestHandshake(t *testing.T) { ...@@ -585,8 +593,7 @@ func TestHandshake(t *testing.T) {
if !bytes.Equal(got.Syn.ObservedUnderlay, node2maBinary) { if !bytes.Equal(got.Syn.ObservedUnderlay, node2maBinary) {
t.Fatalf("got bad syn") t.Fatalf("got bad syn")
} }
bzzAddress, err := bzz.ParseAddress(got.Ack.Address.Underlay, got.Ack.Address.Overlay, got.Ack.Address.Signature, got.Ack.Transaction, blockhash, got.Ack.NetworkID)
bzzAddress, err := bzz.ParseAddress(got.Ack.Address.Underlay, got.Ack.Address.Overlay, got.Ack.Address.Signature, got.Ack.NetworkID)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
...@@ -638,9 +645,9 @@ func TestHandshake(t *testing.T) { ...@@ -638,9 +645,9 @@ func TestHandshake(t *testing.T) {
}) })
t.Run("Handle - transaction is not on the blockchain", func(t *testing.T) { t.Run("Handle - transaction is not on the blockchain", func(t *testing.T) {
sbMock := &MockSenderMatcher{v: false} sbMock := &MockSenderMatcher{v: false, blockHash: blockhash}
handshakeService, err := handshake.New(signer1, aaddresser, sbMock, node1Info.BzzAddress.Overlay, networkID, true, []byte("0xff"), "", logger) handshakeService, err := handshake.New(signer1, aaddresser, sbMock, node1Info.BzzAddress.Overlay, networkID, true, trxHash, "", logger)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
...@@ -662,15 +669,16 @@ func TestHandshake(t *testing.T) { ...@@ -662,15 +669,16 @@ func TestHandshake(t *testing.T) {
Overlay: node2BzzAddress.Overlay.Bytes(), Overlay: node2BzzAddress.Overlay.Bytes(),
Signature: node2BzzAddress.Signature, Signature: node2BzzAddress.Signature,
}, },
NetworkID: networkID, NetworkID: networkID,
FullNode: true, FullNode: true,
Transaction: trxHash,
}); err != nil { }); err != nil {
t.Fatal(err) t.Fatal(err)
} }
_, err = handshakeService.Handle(context.Background(), stream1, node2AddrInfo.Addrs[0], node2AddrInfo.ID) _, err = handshakeService.Handle(context.Background(), stream1, node2AddrInfo.Addrs[0], node2AddrInfo.ID)
if !errors.Is(err, handshake.ErrAddressNotFound) { if err == nil {
t.Fatalf("expected error %v, got %v", handshake.ErrAddressNotFound, err) t.Fatalf("expected error, got nil")
} }
}) })
...@@ -734,9 +742,15 @@ func (a *AdvertisableAddresserMock) Resolve(observedAdddress ma.Multiaddr) (ma.M ...@@ -734,9 +742,15 @@ func (a *AdvertisableAddresserMock) Resolve(observedAdddress ma.Multiaddr) (ma.M
} }
type MockSenderMatcher struct { type MockSenderMatcher struct {
v bool v bool
blockHash []byte
} }
func (m MockSenderMatcher) Matches(context.Context, []byte, uint64, swarm.Address) (bool, error) { func (m MockSenderMatcher) Matches(context.Context, []byte, uint64, swarm.Address) ([]byte, error) {
return m.v, nil
if m.v {
return m.blockHash, nil
}
return nil, errors.New("")
} }
...@@ -13,7 +13,7 @@ import ( ...@@ -13,7 +13,7 @@ import (
"testing" "testing"
"time" "time"
"github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/common"
"github.com/ethersphere/bee/pkg/addressbook" "github.com/ethersphere/bee/pkg/addressbook"
"github.com/ethersphere/bee/pkg/crypto" "github.com/ethersphere/bee/pkg/crypto"
"github.com/ethersphere/bee/pkg/logging" "github.com/ethersphere/bee/pkg/logging"
...@@ -43,7 +43,10 @@ func newService(t *testing.T, networkID uint64, o libp2pServiceOpts) (s *libp2p. ...@@ -43,7 +43,10 @@ func newService(t *testing.T, networkID uint64, o libp2pServiceOpts) (s *libp2p.
t.Fatal(err) t.Fatal(err)
} }
overlay, err = crypto.NewOverlayAddress(swarmKey.PublicKey, networkID) trx := common.HexToHash("0x1").Bytes()
blockHash := common.HexToHash("0x2").Bytes()
overlay, err = crypto.NewOverlayAddress(swarmKey.PublicKey, networkID, blockHash)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
...@@ -74,9 +77,11 @@ func newService(t *testing.T, networkID uint64, o libp2pServiceOpts) (s *libp2p. ...@@ -74,9 +77,11 @@ func newService(t *testing.T, networkID uint64, o libp2pServiceOpts) (s *libp2p.
o.lightNodes = lightnode.NewContainer(overlay) o.lightNodes = lightnode.NewContainer(overlay)
} }
opts := o.libp2pOpts opts := o.libp2pOpts
opts.Transaction = []byte(hexutil.EncodeUint64(o.PrivateKey.Y.Uint64())) opts.Transaction = trx
senderMatcher := &MockSenderMatcher{} senderMatcher := &MockSenderMatcher{
BlockHash: blockHash,
}
s, err = libp2p.New(ctx, crypto.NewDefaultSigner(swarmKey), networkID, overlay, addr, o.Addressbook, statestore, o.lightNodes, senderMatcher, o.Logger, nil, opts) s, err = libp2p.New(ctx, crypto.NewDefaultSigner(swarmKey), networkID, overlay, addr, o.Addressbook, statestore, o.lightNodes, senderMatcher, o.Logger, nil, opts)
if err != nil { if err != nil {
...@@ -160,8 +165,10 @@ func serviceUnderlayAddress(t *testing.T, s *libp2p.Service) multiaddr.Multiaddr ...@@ -160,8 +165,10 @@ func serviceUnderlayAddress(t *testing.T, s *libp2p.Service) multiaddr.Multiaddr
return addrs[0] return addrs[0]
} }
type MockSenderMatcher struct{} type MockSenderMatcher struct {
BlockHash []byte
}
func (m MockSenderMatcher) Matches(context.Context, []byte, uint64, swarm.Address) (bool, error) { func (m MockSenderMatcher) Matches(context.Context, []byte, uint64, swarm.Address) ([]byte, error) {
return true, nil return m.BlockHash, nil
} }
...@@ -205,7 +205,7 @@ LOOP: ...@@ -205,7 +205,7 @@ LOOP:
return return
} }
storerPeer, err = crypto.NewOverlayAddress(*publicKey, s.networkID) storerPeer, err = crypto.NewOverlayAddress(*publicKey, s.networkID, receipt.BlockHash)
if err != nil { if err != nil {
err = fmt.Errorf("pusher: receipt storer address: %w", err) err = fmt.Errorf("pusher: receipt storer address: %w", err)
return return
......
...@@ -13,6 +13,7 @@ import ( ...@@ -13,6 +13,7 @@ import (
"testing" "testing"
"time" "time"
"github.com/ethereum/go-ethereum/common"
"github.com/ethersphere/bee/pkg/crypto" "github.com/ethersphere/bee/pkg/crypto"
statestore "github.com/ethersphere/bee/pkg/statestore/mock" statestore "github.com/ethersphere/bee/pkg/statestore/mock"
...@@ -30,6 +31,7 @@ import ( ...@@ -30,6 +31,7 @@ import (
// no of times to retry to see if we have received response from pushsync // no of times to retry to see if we have received response from pushsync
var noOfRetries = 20 var noOfRetries = 20
var block = common.HexToHash("0x1").Bytes()
// Wrap the actual storer to intercept the modeSet that the pusher will call when a valid receipt is received // Wrap the actual storer to intercept the modeSet that the pusher will call when a valid receipt is received
type Store struct { type Store struct {
...@@ -84,6 +86,7 @@ func TestSendChunkToSyncWithTag(t *testing.T) { ...@@ -84,6 +86,7 @@ func TestSendChunkToSyncWithTag(t *testing.T) {
receipt := &pushsync.Receipt{ receipt := &pushsync.Receipt{
Address: swarm.NewAddress(chunk.Address().Bytes()), Address: swarm.NewAddress(chunk.Address().Bytes()),
Signature: signature, Signature: signature,
BlockHash: block,
} }
return receipt, nil return receipt, nil
}) })
...@@ -140,6 +143,7 @@ func TestSendChunkToPushSyncWithoutTag(t *testing.T) { ...@@ -140,6 +143,7 @@ func TestSendChunkToPushSyncWithoutTag(t *testing.T) {
receipt := &pushsync.Receipt{ receipt := &pushsync.Receipt{
Address: swarm.NewAddress(chunk.Address().Bytes()), Address: swarm.NewAddress(chunk.Address().Bytes()),
Signature: signature, Signature: signature,
BlockHash: block,
} }
return receipt, nil return receipt, nil
}) })
...@@ -225,6 +229,7 @@ func TestSendChunkAndTimeoutinReceivingReceipt(t *testing.T) { ...@@ -225,6 +229,7 @@ func TestSendChunkAndTimeoutinReceivingReceipt(t *testing.T) {
receipt := &pushsync.Receipt{ receipt := &pushsync.Receipt{
Address: swarm.NewAddress(chunk.Address().Bytes()), Address: swarm.NewAddress(chunk.Address().Bytes()),
Signature: signature, Signature: signature,
BlockHash: block,
} }
return receipt, nil return receipt, nil
}) })
...@@ -280,6 +285,7 @@ func TestPusherClose(t *testing.T) { ...@@ -280,6 +285,7 @@ func TestPusherClose(t *testing.T) {
receipt := &pushsync.Receipt{ receipt := &pushsync.Receipt{
Address: swarm.NewAddress(chunk.Address().Bytes()), Address: swarm.NewAddress(chunk.Address().Bytes()),
Signature: signature, Signature: signature,
BlockHash: block,
} }
return receipt, nil return receipt, nil
}) })
...@@ -383,6 +389,7 @@ func TestPusherRetryShallow(t *testing.T) { ...@@ -383,6 +389,7 @@ func TestPusherRetryShallow(t *testing.T) {
receipt := &pushsync.Receipt{ receipt := &pushsync.Receipt{
Address: swarm.NewAddress(chunk.Address().Bytes()), Address: swarm.NewAddress(chunk.Address().Bytes()),
Signature: signature, Signature: signature,
BlockHash: block,
} }
return receipt, nil return receipt, nil
}) })
...@@ -457,7 +464,3 @@ func checkIfModeSet(addr swarm.Address, mode storage.ModeSet, storer *Store) err ...@@ -457,7 +464,3 @@ func checkIfModeSet(addr swarm.Address, mode storage.ModeSet, storer *Store) err
} }
return nil return nil
} }
// To avoid timeout during race testing
// cd pkg/pusher
// go test -race -count 1000 -timeout 60m .
...@@ -85,6 +85,7 @@ func (m *Delivery) GetStamp() []byte { ...@@ -85,6 +85,7 @@ func (m *Delivery) GetStamp() []byte {
type Receipt struct { type Receipt struct {
Address []byte `protobuf:"bytes,1,opt,name=Address,proto3" json:"Address,omitempty"` Address []byte `protobuf:"bytes,1,opt,name=Address,proto3" json:"Address,omitempty"`
Signature []byte `protobuf:"bytes,2,opt,name=Signature,proto3" json:"Signature,omitempty"` Signature []byte `protobuf:"bytes,2,opt,name=Signature,proto3" json:"Signature,omitempty"`
BlockHash []byte `protobuf:"bytes,3,opt,name=BlockHash,proto3" json:"BlockHash,omitempty"`
} }
func (m *Receipt) Reset() { *m = Receipt{} } func (m *Receipt) Reset() { *m = Receipt{} }
...@@ -134,6 +135,13 @@ func (m *Receipt) GetSignature() []byte { ...@@ -134,6 +135,13 @@ func (m *Receipt) GetSignature() []byte {
return nil return nil
} }
func (m *Receipt) GetBlockHash() []byte {
if m != nil {
return m.BlockHash
}
return nil
}
func init() { func init() {
proto.RegisterType((*Delivery)(nil), "pushsync.Delivery") proto.RegisterType((*Delivery)(nil), "pushsync.Delivery")
proto.RegisterType((*Receipt)(nil), "pushsync.Receipt") proto.RegisterType((*Receipt)(nil), "pushsync.Receipt")
...@@ -142,18 +150,19 @@ func init() { ...@@ -142,18 +150,19 @@ func init() {
func init() { proto.RegisterFile("pushsync.proto", fileDescriptor_723cf31bfc02bfd6) } func init() { proto.RegisterFile("pushsync.proto", fileDescriptor_723cf31bfc02bfd6) }
var fileDescriptor_723cf31bfc02bfd6 = []byte{ var fileDescriptor_723cf31bfc02bfd6 = []byte{
// 170 bytes of a gzipped FileDescriptorProto // 185 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xe2, 0x2b, 0x28, 0x2d, 0xce, 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xe2, 0x2b, 0x28, 0x2d, 0xce,
0x28, 0xae, 0xcc, 0x4b, 0xd6, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0xe2, 0x80, 0xf1, 0x95, 0xfc, 0x28, 0xae, 0xcc, 0x4b, 0xd6, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0xe2, 0x80, 0xf1, 0x95, 0xfc,
0xb8, 0x38, 0x5c, 0x52, 0x73, 0x32, 0xcb, 0x52, 0x8b, 0x2a, 0x85, 0x24, 0xb8, 0xd8, 0x1d, 0x53, 0xb8, 0x38, 0x5c, 0x52, 0x73, 0x32, 0xcb, 0x52, 0x8b, 0x2a, 0x85, 0x24, 0xb8, 0xd8, 0x1d, 0x53,
0x52, 0x8a, 0x52, 0x8b, 0x8b, 0x25, 0x18, 0x15, 0x18, 0x35, 0x78, 0x82, 0x60, 0x5c, 0x21, 0x21, 0x52, 0x8a, 0x52, 0x8b, 0x8b, 0x25, 0x18, 0x15, 0x18, 0x35, 0x78, 0x82, 0x60, 0x5c, 0x21, 0x21,
0x2e, 0x16, 0x97, 0xc4, 0x92, 0x44, 0x09, 0x26, 0xb0, 0x30, 0x98, 0x2d, 0x24, 0xc2, 0xc5, 0x1a, 0x2e, 0x16, 0x97, 0xc4, 0x92, 0x44, 0x09, 0x26, 0xb0, 0x30, 0x98, 0x2d, 0x24, 0xc2, 0xc5, 0x1a,
0x5c, 0x92, 0x98, 0x5b, 0x20, 0xc1, 0x0c, 0x16, 0x84, 0x70, 0x94, 0x1c, 0xb9, 0xd8, 0x83, 0x52, 0x5c, 0x92, 0x98, 0x5b, 0x20, 0xc1, 0x0c, 0x16, 0x84, 0x70, 0x94, 0xe2, 0xb9, 0xd8, 0x83, 0x52,
0x93, 0x53, 0x33, 0x0b, 0x4a, 0xf0, 0x18, 0x27, 0xc3, 0xc5, 0x19, 0x9c, 0x99, 0x9e, 0x97, 0x58, 0x93, 0x53, 0x33, 0x0b, 0x4a, 0xf0, 0x18, 0x27, 0xc3, 0xc5, 0x19, 0x9c, 0x99, 0x9e, 0x97, 0x58,
0x52, 0x5a, 0x94, 0x0a, 0x35, 0x13, 0x21, 0xe0, 0x24, 0x73, 0xe2, 0x91, 0x1c, 0xe3, 0x85, 0x47, 0x52, 0x5a, 0x94, 0x0a, 0x35, 0x13, 0x21, 0x00, 0x92, 0x75, 0xca, 0xc9, 0x4f, 0xce, 0xf6, 0x48,
0x72, 0x8c, 0x0f, 0x1e, 0xc9, 0x31, 0x4e, 0x78, 0x2c, 0xc7, 0x70, 0xe1, 0xb1, 0x1c, 0xc3, 0x8d, 0x2c, 0xce, 0x80, 0x1a, 0x8e, 0x10, 0x70, 0x92, 0x39, 0xf1, 0x48, 0x8e, 0xf1, 0xc2, 0x23, 0x39,
0xc7, 0x72, 0x0c, 0x51, 0x4c, 0x05, 0x49, 0x49, 0x6c, 0x60, 0x1f, 0x18, 0x03, 0x02, 0x00, 0x00, 0xc6, 0x07, 0x8f, 0xe4, 0x18, 0x27, 0x3c, 0x96, 0x63, 0xb8, 0xf0, 0x58, 0x8e, 0xe1, 0xc6, 0x63,
0xff, 0xff, 0xbb, 0xdf, 0x60, 0x63, 0xd3, 0x00, 0x00, 0x00, 0x39, 0x86, 0x28, 0xa6, 0x82, 0xa4, 0x24, 0x36, 0xb0, 0xff, 0x8c, 0x01, 0x01, 0x00, 0x00, 0xff,
0xff, 0xd8, 0x59, 0x25, 0xda, 0xf1, 0x00, 0x00, 0x00,
} }
func (m *Delivery) Marshal() (dAtA []byte, err error) { func (m *Delivery) Marshal() (dAtA []byte, err error) {
...@@ -220,6 +229,13 @@ func (m *Receipt) MarshalToSizedBuffer(dAtA []byte) (int, error) { ...@@ -220,6 +229,13 @@ func (m *Receipt) MarshalToSizedBuffer(dAtA []byte) (int, error) {
_ = i _ = i
var l int var l int
_ = l _ = l
if len(m.BlockHash) > 0 {
i -= len(m.BlockHash)
copy(dAtA[i:], m.BlockHash)
i = encodeVarintPushsync(dAtA, i, uint64(len(m.BlockHash)))
i--
dAtA[i] = 0x1a
}
if len(m.Signature) > 0 { if len(m.Signature) > 0 {
i -= len(m.Signature) i -= len(m.Signature)
copy(dAtA[i:], m.Signature) copy(dAtA[i:], m.Signature)
...@@ -283,6 +299,10 @@ func (m *Receipt) Size() (n int) { ...@@ -283,6 +299,10 @@ func (m *Receipt) Size() (n int) {
if l > 0 { if l > 0 {
n += 1 + l + sovPushsync(uint64(l)) n += 1 + l + sovPushsync(uint64(l))
} }
l = len(m.BlockHash)
if l > 0 {
n += 1 + l + sovPushsync(uint64(l))
}
return n return n
} }
...@@ -544,6 +564,40 @@ func (m *Receipt) Unmarshal(dAtA []byte) error { ...@@ -544,6 +564,40 @@ func (m *Receipt) Unmarshal(dAtA []byte) error {
m.Signature = []byte{} m.Signature = []byte{}
} }
iNdEx = postIndex iNdEx = postIndex
case 3:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field BlockHash", wireType)
}
var byteLen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowPushsync
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
byteLen |= int(b&0x7F) << shift
if b < 0x80 {
break
}
}
if byteLen < 0 {
return ErrInvalidLengthPushsync
}
postIndex := iNdEx + byteLen
if postIndex < 0 {
return ErrInvalidLengthPushsync
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.BlockHash = append(m.BlockHash[:0], dAtA[iNdEx:postIndex]...)
if m.BlockHash == nil {
m.BlockHash = []byte{}
}
iNdEx = postIndex
default: default:
iNdEx = preIndex iNdEx = preIndex
skippy, err := skipPushsync(dAtA[iNdEx:]) skippy, err := skipPushsync(dAtA[iNdEx:])
......
...@@ -17,4 +17,5 @@ message Delivery { ...@@ -17,4 +17,5 @@ message Delivery {
message Receipt { message Receipt {
bytes Address = 1; bytes Address = 1;
bytes Signature = 2; bytes Signature = 2;
bytes BlockHash = 3;
} }
...@@ -55,10 +55,12 @@ type PushSyncer interface { ...@@ -55,10 +55,12 @@ type PushSyncer interface {
type Receipt struct { type Receipt struct {
Address swarm.Address Address swarm.Address
Signature []byte Signature []byte
BlockHash []byte
} }
type PushSync struct { type PushSync struct {
address swarm.Address address swarm.Address
blockHash []byte
streamer p2p.StreamerDisconnecter streamer p2p.StreamerDisconnecter
storer storage.Putter storer storage.Putter
topologyDriver topology.Driver topologyDriver topology.Driver
...@@ -80,9 +82,10 @@ var defaultTTL = 20 * time.Second // request time to live ...@@ -80,9 +82,10 @@ var defaultTTL = 20 * time.Second // request time to live
var timeToWaitForPushsyncToNeighbor = 3 * time.Second // time to wait to get a receipt for a chunk var timeToWaitForPushsyncToNeighbor = 3 * time.Second // time to wait to get a receipt for a chunk
var nPeersToPushsync = 3 // number of peers to replicate to as receipt is sent upstream var nPeersToPushsync = 3 // number of peers to replicate to as receipt is sent upstream
func New(address swarm.Address, streamer p2p.StreamerDisconnecter, storer storage.Putter, topology topology.Driver, tagger *tags.Tags, isFullNode bool, unwrap func(swarm.Chunk), validStamp func(swarm.Chunk, []byte) (swarm.Chunk, error), logger logging.Logger, accounting accounting.Interface, pricer pricer.Interface, signer crypto.Signer, tracer *tracing.Tracer, warmupTime time.Duration) *PushSync { func New(address swarm.Address, blockHash []byte, streamer p2p.StreamerDisconnecter, storer storage.Putter, topology topology.Driver, tagger *tags.Tags, isFullNode bool, unwrap func(swarm.Chunk), validStamp func(swarm.Chunk, []byte) (swarm.Chunk, error), logger logging.Logger, accounting accounting.Interface, pricer pricer.Interface, signer crypto.Signer, tracer *tracing.Tracer, warmupTime time.Duration) *PushSync {
ps := &PushSync{ ps := &PushSync{
address: address, address: address,
blockHash: blockHash,
streamer: streamer, streamer: streamer,
storer: storer, storer: storer,
topologyDriver: topology, topologyDriver: topology,
...@@ -174,7 +177,7 @@ func (ps *PushSync) handler(ctx context.Context, p p2p.Peer, stream p2p.Stream) ...@@ -174,7 +177,7 @@ func (ps *PushSync) handler(ctx context.Context, p p2p.Peer, stream p2p.Stream)
if err != nil { if err != nil {
return fmt.Errorf("receipt signature: %w", err) return fmt.Errorf("receipt signature: %w", err)
} }
receipt := pb.Receipt{Address: bytes, Signature: signature} receipt := pb.Receipt{Address: bytes, Signature: signature, BlockHash: ps.blockHash}
if err := w.WriteMsgWithContext(ctxd, &receipt); err != nil { if err := w.WriteMsgWithContext(ctxd, &receipt); err != nil {
return fmt.Errorf("send receipt to peer %s: %w", p.Address.String(), err) return fmt.Errorf("send receipt to peer %s: %w", p.Address.String(), err)
} }
...@@ -222,7 +225,7 @@ func (ps *PushSync) handler(ctx context.Context, p p2p.Peer, stream p2p.Stream) ...@@ -222,7 +225,7 @@ func (ps *PushSync) handler(ctx context.Context, p p2p.Peer, stream p2p.Stream)
} }
defer debit.Cleanup() defer debit.Cleanup()
receipt := pb.Receipt{Address: chunk.Address().Bytes(), Signature: signature} receipt := pb.Receipt{Address: chunk.Address().Bytes(), Signature: signature, BlockHash: ps.blockHash}
if err := w.WriteMsgWithContext(ctx, &receipt); err != nil { if err := w.WriteMsgWithContext(ctx, &receipt); err != nil {
return fmt.Errorf("send receipt to peer %s: %w", p.Address.String(), err) return fmt.Errorf("send receipt to peer %s: %w", p.Address.String(), err)
} }
...@@ -257,7 +260,8 @@ func (ps *PushSync) PushChunkToClosest(ctx context.Context, ch swarm.Chunk) (*Re ...@@ -257,7 +260,8 @@ func (ps *PushSync) PushChunkToClosest(ctx context.Context, ch swarm.Chunk) (*Re
} }
return &Receipt{ return &Receipt{
Address: swarm.NewAddress(r.Address), Address: swarm.NewAddress(r.Address),
Signature: r.Signature}, nil Signature: r.Signature,
BlockHash: r.BlockHash}, nil
} }
type pushResult struct { type pushResult struct {
......
...@@ -13,6 +13,7 @@ import ( ...@@ -13,6 +13,7 @@ import (
"testing" "testing"
"time" "time"
"github.com/ethereum/go-ethereum/common"
"github.com/ethersphere/bee/pkg/accounting" "github.com/ethersphere/bee/pkg/accounting"
accountingmock "github.com/ethersphere/bee/pkg/accounting/mock" accountingmock "github.com/ethersphere/bee/pkg/accounting/mock"
"github.com/ethersphere/bee/pkg/crypto" "github.com/ethersphere/bee/pkg/crypto"
...@@ -39,6 +40,8 @@ const ( ...@@ -39,6 +40,8 @@ const (
fixedPrice = uint64(10) fixedPrice = uint64(10)
) )
var blockHash = common.HexToHash("0x1")
type pricerParameters struct { type pricerParameters struct {
price uint64 price uint64
peerPrice uint64 peerPrice uint64
...@@ -776,6 +779,10 @@ func TestSignsReceipt(t *testing.T) { ...@@ -776,6 +779,10 @@ func TestSignsReceipt(t *testing.T) {
if !bytes.Equal([]byte{1}, receipt.Signature) { if !bytes.Equal([]byte{1}, receipt.Signature) {
t.Fatal("receipt signature is not present") t.Fatal("receipt signature is not present")
} }
if !bytes.Equal(blockHash.Bytes(), receipt.BlockHash) {
t.Fatal("receipt block hash do not match")
}
} }
func createPushSyncNode(t *testing.T, addr swarm.Address, prices pricerParameters, recorder *streamtest.Recorder, unwrap func(swarm.Chunk), signer crypto.Signer, mockOpts ...mock.Option) (*pushsync.PushSync, *mocks.MockStorer, *tags.Tags, accounting.Interface) { func createPushSyncNode(t *testing.T, addr swarm.Address, prices pricerParameters, recorder *streamtest.Recorder, unwrap func(swarm.Chunk), signer crypto.Signer, mockOpts ...mock.Option) (*pushsync.PushSync, *mocks.MockStorer, *tags.Tags, accounting.Interface) {
...@@ -804,7 +811,7 @@ func createPushSyncNodeWithAccounting(t *testing.T, addr swarm.Address, prices p ...@@ -804,7 +811,7 @@ func createPushSyncNodeWithAccounting(t *testing.T, addr swarm.Address, prices p
return ch.WithStamp(postage.NewStamp(nil, nil, nil, nil)), nil return ch.WithStamp(postage.NewStamp(nil, nil, nil, nil)), nil
} }
return pushsync.New(addr, recorderDisconnecter, storer, mockTopology, mtag, true, unwrap, validStamp, logger, acct, mockPricer, signer, nil, 0), storer, mtag return pushsync.New(addr, blockHash.Bytes(), recorderDisconnecter, storer, mockTopology, mtag, true, unwrap, validStamp, logger, acct, mockPricer, signer, nil, 0), storer, mtag
} }
func waitOnRecordAndTest(t *testing.T, peer swarm.Address, recorder *streamtest.Recorder, add swarm.Address, data []byte) { func waitOnRecordAndTest(t *testing.T, peer swarm.Address, recorder *streamtest.Recorder, add swarm.Address, data []byte) {
......
...@@ -11,7 +11,6 @@ import ( ...@@ -11,7 +11,6 @@ import (
"math/big" "math/big"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethersphere/bee/pkg/crypto"
"github.com/ethersphere/bee/pkg/logging" "github.com/ethersphere/bee/pkg/logging"
"github.com/ethersphere/bee/pkg/settlement" "github.com/ethersphere/bee/pkg/settlement"
"github.com/ethersphere/bee/pkg/settlement/swap/chequebook" "github.com/ethersphere/bee/pkg/settlement/swap/chequebook"
...@@ -237,13 +236,6 @@ func (s *Service) SettlementsReceived() (map[string]*big.Int, error) { ...@@ -237,13 +236,6 @@ func (s *Service) SettlementsReceived() (map[string]*big.Int, error) {
// Handshake is called by the swap protocol when a handshake is received. // Handshake is called by the swap protocol when a handshake is received.
func (s *Service) Handshake(peer swarm.Address, beneficiary common.Address) error { func (s *Service) Handshake(peer swarm.Address, beneficiary common.Address) error {
// check that the overlay address was derived from the beneficiary (implying they have the same private key)
// while this is not strictly necessary for correct functionality we need to ensure no two peers use the same beneficiary
// as long as we enforce this we might not need the handshake message if the p2p layer exposed the overlay public key
expectedOverlay := crypto.NewOverlayFromEthereumAddress(beneficiary[:], s.networkID)
if !expectedOverlay.Equal(peer) {
return ErrWrongBeneficiary
}
storedBeneficiary, known, err := s.addressbook.Beneficiary(peer) storedBeneficiary, known, err := s.addressbook.Beneficiary(peer)
if err != nil { if err != nil {
......
...@@ -527,7 +527,9 @@ func TestHandshake(t *testing.T) { ...@@ -527,7 +527,9 @@ func TestHandshake(t *testing.T) {
beneficiary := common.HexToAddress("0xcd") beneficiary := common.HexToAddress("0xcd")
networkID := uint64(1) networkID := uint64(1)
peer := crypto.NewOverlayFromEthereumAddress(beneficiary[:], networkID) txHash := common.HexToHash("0x1")
peer := crypto.NewOverlayFromEthereumAddress(beneficiary[:], networkID, txHash.Bytes())
var putCalled bool var putCalled bool
swapService := swap.New( swapService := swap.New(
...@@ -565,8 +567,9 @@ func TestHandshakeNewPeer(t *testing.T) { ...@@ -565,8 +567,9 @@ func TestHandshakeNewPeer(t *testing.T) {
store := mockstore.NewStateStore() store := mockstore.NewStateStore()
beneficiary := common.HexToAddress("0xcd") beneficiary := common.HexToAddress("0xcd")
trx := common.HexToHash("0x1")
networkID := uint64(1) networkID := uint64(1)
peer := crypto.NewOverlayFromEthereumAddress(beneficiary[:], networkID) peer := crypto.NewOverlayFromEthereumAddress(beneficiary[:], networkID, trx.Bytes())
var putCalled bool var putCalled bool
swapService := swap.New( swapService := swap.New(
...@@ -600,6 +603,9 @@ func TestHandshakeNewPeer(t *testing.T) { ...@@ -600,6 +603,9 @@ func TestHandshakeNewPeer(t *testing.T) {
} }
func TestHandshakeWrongBeneficiary(t *testing.T) { func TestHandshakeWrongBeneficiary(t *testing.T) {
t.Skip()
logger := logging.New(ioutil.Discard, 0) logger := logging.New(ioutil.Discard, 0)
store := mockstore.NewStateStore() store := mockstore.NewStateStore()
......
...@@ -167,7 +167,6 @@ func (s *Service) init(ctx context.Context, p p2p.Peer) error { ...@@ -167,7 +167,6 @@ func (s *Service) init(ctx context.Context, p p2p.Peer) error {
} }
beneficiary := common.BytesToAddress(req.Beneficiary) beneficiary := common.BytesToAddress(req.Beneficiary)
return s.swap.Handshake(p.Address, beneficiary) return s.swap.Handshake(p.Address, beneficiary)
} }
......
...@@ -733,7 +733,7 @@ func TestAddressBookPrune(t *testing.T) { ...@@ -733,7 +733,7 @@ func TestAddressBookPrune(t *testing.T) {
} }
defer kad.Close() defer kad.Close()
nonConnPeer, err := bzz.NewAddress(signer, nonConnectableAddress, test.RandomAddressAt(base, 1), 0) nonConnPeer, err := bzz.NewAddress(signer, nonConnectableAddress, test.RandomAddressAt(base, 1), 0, nil)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
...@@ -809,7 +809,7 @@ func TestAddressBookQuickPrune(t *testing.T) { ...@@ -809,7 +809,7 @@ func TestAddressBookQuickPrune(t *testing.T) {
time.Sleep(100 * time.Millisecond) time.Sleep(100 * time.Millisecond)
nonConnPeer, err := bzz.NewAddress(signer, nonConnectableAddress, test.RandomAddressAt(base, 1), 0) nonConnPeer, err := bzz.NewAddress(signer, nonConnectableAddress, test.RandomAddressAt(base, 1), 0, nil)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
...@@ -1117,7 +1117,7 @@ func TestStart(t *testing.T) { ...@@ -1117,7 +1117,7 @@ func TestStart(t *testing.T) {
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
bzzAddr, err := bzz.NewAddress(signer, multiaddr, peer, 0) bzzAddr, err := bzz.NewAddress(signer, multiaddr, peer, 0, nil)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
...@@ -1197,7 +1197,7 @@ func p2pMock(ab addressbook.Interface, signer beeCrypto.Signer, counter, failedC ...@@ -1197,7 +1197,7 @@ func p2pMock(ab addressbook.Interface, signer beeCrypto.Signer, counter, failedC
} }
address := test.RandomAddress() address := test.RandomAddress()
bzzAddr, err := bzz.NewAddress(signer, addr, address, 0) bzzAddr, err := bzz.NewAddress(signer, addr, address, 0, nil)
if err != nil { if err != nil {
return nil, err return nil, err
} }
...@@ -1232,7 +1232,7 @@ func connectOne(t *testing.T, signer beeCrypto.Signer, k *kademlia.Kad, ab addre ...@@ -1232,7 +1232,7 @@ func connectOne(t *testing.T, signer beeCrypto.Signer, k *kademlia.Kad, ab addre
t.Fatal(err) t.Fatal(err)
} }
bzzAddr, err := bzz.NewAddress(signer, multiaddr, peer, 0) bzzAddr, err := bzz.NewAddress(signer, multiaddr, peer, 0, nil)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
...@@ -1253,7 +1253,7 @@ func addOne(t *testing.T, signer beeCrypto.Signer, k *kademlia.Kad, ab addressbo ...@@ -1253,7 +1253,7 @@ func addOne(t *testing.T, signer beeCrypto.Signer, k *kademlia.Kad, ab addressbo
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
bzzAddr, err := bzz.NewAddress(signer, multiaddr, peer, 0) bzzAddr, err := bzz.NewAddress(signer, multiaddr, peer, 0, nil)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
......
...@@ -6,11 +6,13 @@ package transaction ...@@ -6,11 +6,13 @@ package transaction
import ( import (
"context" "context"
"errors"
"fmt" "fmt"
"math/big" "math/big"
"strings" "strings"
"time" "time"
"github.com/ethereum/go-ethereum"
"github.com/ethereum/go-ethereum/accounts/abi" "github.com/ethereum/go-ethereum/accounts/abi"
"github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
...@@ -23,6 +25,7 @@ type Backend interface { ...@@ -23,6 +25,7 @@ type Backend interface {
TransactionReceipt(ctx context.Context, txHash common.Hash) (*types.Receipt, error) TransactionReceipt(ctx context.Context, txHash common.Hash) (*types.Receipt, error)
TransactionByHash(ctx context.Context, hash common.Hash) (tx *types.Transaction, isPending bool, err error) TransactionByHash(ctx context.Context, hash common.Hash) (tx *types.Transaction, isPending bool, err error)
BlockNumber(ctx context.Context) (uint64, error) BlockNumber(ctx context.Context) (uint64, error)
BlockByNumber(ctx context.Context, number *big.Int) (*types.Block, error)
HeaderByNumber(ctx context.Context, number *big.Int) (*types.Header, error) HeaderByNumber(ctx context.Context, number *big.Int) (*types.Header, error)
BalanceAt(ctx context.Context, address common.Address, block *big.Int) (*big.Int, error) BalanceAt(ctx context.Context, address common.Address, block *big.Int) (*big.Int, error)
NonceAt(ctx context.Context, account common.Address, blockNumber *big.Int) (uint64, error) NonceAt(ctx context.Context, account common.Address, blockNumber *big.Int) (uint64, error)
...@@ -70,6 +73,25 @@ func WaitSynced(ctx context.Context, backend Backend, maxDelay time.Duration) er ...@@ -70,6 +73,25 @@ func WaitSynced(ctx context.Context, backend Backend, maxDelay time.Duration) er
} }
} }
func WaitBlock(ctx context.Context, backend Backend, pollingInterval time.Duration, block *big.Int) (*types.Block, error) {
for {
block, err := backend.BlockByNumber(ctx, block)
if err != nil {
if !errors.Is(err, ethereum.NotFound) {
return nil, err
}
} else {
return block, nil
}
select {
case <-time.After(pollingInterval):
case <-ctx.Done():
return nil, errors.New("context timeout")
}
}
}
// ParseABIUnchecked will parse a valid json abi. Only use this with string constants known to be correct. // ParseABIUnchecked will parse a valid json abi. Only use this with string constants known to be correct.
func ParseABIUnchecked(json string) abi.ABI { func ParseABIUnchecked(json string) abi.ABI {
cabi, err := abi.JSON(strings.NewReader(json)) cabi, err := abi.JSON(strings.NewReader(json))
......
...@@ -24,6 +24,7 @@ type backendMock struct { ...@@ -24,6 +24,7 @@ type backendMock struct {
pendingNonceAt func(ctx context.Context, account common.Address) (uint64, error) pendingNonceAt func(ctx context.Context, account common.Address) (uint64, error)
transactionByHash func(ctx context.Context, hash common.Hash) (tx *types.Transaction, isPending bool, err error) transactionByHash func(ctx context.Context, hash common.Hash) (tx *types.Transaction, isPending bool, err error)
blockNumber func(ctx context.Context) (uint64, error) blockNumber func(ctx context.Context) (uint64, error)
blockByNumber func(ctx context.Context, number *big.Int) (*types.Block, error)
headerByNumber func(ctx context.Context, number *big.Int) (*types.Header, error) headerByNumber func(ctx context.Context, number *big.Int) (*types.Header, error)
balanceAt func(ctx context.Context, address common.Address, block *big.Int) (*big.Int, error) balanceAt func(ctx context.Context, address common.Address, block *big.Int) (*big.Int, error)
nonceAt func(ctx context.Context, account common.Address, blockNumber *big.Int) (uint64, error) nonceAt func(ctx context.Context, account common.Address, blockNumber *big.Int) (uint64, error)
...@@ -101,6 +102,13 @@ func (m *backendMock) BlockNumber(ctx context.Context) (uint64, error) { ...@@ -101,6 +102,13 @@ func (m *backendMock) BlockNumber(ctx context.Context) (uint64, error) {
return 0, errors.New("not implemented") return 0, errors.New("not implemented")
} }
func (m *backendMock) BlockByNumber(ctx context.Context, number *big.Int) (*types.Block, error) {
if m.blockNumber != nil {
return m.blockByNumber(ctx, number)
}
return nil, errors.New("not implemented")
}
func (m *backendMock) HeaderByNumber(ctx context.Context, number *big.Int) (*types.Header, error) { func (m *backendMock) HeaderByNumber(ctx context.Context, number *big.Int) (*types.Header, error) {
if m.headerByNumber != nil { if m.headerByNumber != nil {
return m.headerByNumber(ctx, number) return m.headerByNumber(ctx, number)
...@@ -174,6 +182,12 @@ func WithTransactionByHashFunc(f func(ctx context.Context, txHash common.Hash) ( ...@@ -174,6 +182,12 @@ func WithTransactionByHashFunc(f func(ctx context.Context, txHash common.Hash) (
}) })
} }
func WithBlockByNumberFunc(f func(ctx context.Context, number *big.Int) (*types.Block, error)) Option {
return optionFunc(func(s *backendMock) {
s.blockByNumber = f
})
}
func WithSendTransactionFunc(f func(ctx context.Context, tx *types.Transaction) error) Option { func WithSendTransactionFunc(f func(ctx context.Context, tx *types.Transaction) error) Option {
return optionFunc(func(s *backendMock) { return optionFunc(func(s *backendMock) {
s.sendTransaction = f s.sendTransaction = f
......
...@@ -86,6 +86,10 @@ func (m *simulatedBackend) advanceBlock() { ...@@ -86,6 +86,10 @@ func (m *simulatedBackend) advanceBlock() {
} }
} }
func (m *simulatedBackend) BlockByNumber(ctx context.Context, number *big.Int) (*types.Block, error) {
return nil, errors.New("not implemented")
}
func (m *simulatedBackend) CodeAt(ctx context.Context, contract common.Address, blockNumber *big.Int) ([]byte, error) { func (m *simulatedBackend) CodeAt(ctx context.Context, contract common.Address, blockNumber *big.Int) ([]byte, error) {
return nil, errors.New("not implemented") return nil, errors.New("not implemented")
} }
......
...@@ -116,9 +116,11 @@ func (tm *transactionMonitor) watchPending() { ...@@ -116,9 +116,11 @@ func (tm *transactionMonitor) watchPending() {
} }
}() }()
var lastBlock uint64 = 0 var (
lastBlock uint64 = 0
added bool // flag if this iteration was triggered by the watchAdded channel
)
var added bool // flag if this iteration was triggered by the watchAdded channel
for { for {
added = false added = false
select { select {
...@@ -153,7 +155,6 @@ func (tm *transactionMonitor) watchPending() { ...@@ -153,7 +155,6 @@ func (tm *transactionMonitor) watchPending() {
tm.logger.Tracef("error while checking pending transactions: %v", err) tm.logger.Tracef("error while checking pending transactions: %v", err)
continue continue
} }
lastBlock = block lastBlock = block
} }
} }
......
...@@ -5,7 +5,9 @@ ...@@ -5,7 +5,9 @@
package monitormock package monitormock
import ( import (
"context"
"errors" "errors"
"math/big"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
...@@ -14,6 +16,7 @@ import ( ...@@ -14,6 +16,7 @@ import (
type transactionMonitorMock struct { type transactionMonitorMock struct {
watchTransaction func(txHash common.Hash, nonce uint64) (<-chan types.Receipt, <-chan error, error) watchTransaction func(txHash common.Hash, nonce uint64) (<-chan types.Receipt, <-chan error, error)
waitBlock func(ctx context.Context, block *big.Int) (*types.Block, error)
} }
func (m *transactionMonitorMock) WatchTransaction(txHash common.Hash, nonce uint64) (<-chan types.Receipt, <-chan error, error) { func (m *transactionMonitorMock) WatchTransaction(txHash common.Hash, nonce uint64) (<-chan types.Receipt, <-chan error, error) {
...@@ -23,6 +26,13 @@ func (m *transactionMonitorMock) WatchTransaction(txHash common.Hash, nonce uint ...@@ -23,6 +26,13 @@ func (m *transactionMonitorMock) WatchTransaction(txHash common.Hash, nonce uint
return nil, nil, errors.New("not implemented") return nil, nil, errors.New("not implemented")
} }
func (m *transactionMonitorMock) WaitBlock(ctx context.Context, block *big.Int) (*types.Block, error) {
if m.watchTransaction != nil {
return m.waitBlock(ctx, block)
}
return nil, errors.New("not implemented")
}
func (m *transactionMonitorMock) Close() error { func (m *transactionMonitorMock) Close() error {
return nil return nil
} }
...@@ -42,6 +52,12 @@ func WithWatchTransactionFunc(f func(txHash common.Hash, nonce uint64) (<-chan t ...@@ -42,6 +52,12 @@ func WithWatchTransactionFunc(f func(txHash common.Hash, nonce uint64) (<-chan t
}) })
} }
func WithWaitBlockFunc(f func(ctx context.Context, block *big.Int) (*types.Block, error)) Option {
return optionFunc(func(s *transactionMonitorMock) {
s.waitBlock = f
})
}
func New(opts ...Option) transaction.Monitor { func New(opts ...Option) transaction.Monitor {
mock := new(transactionMonitorMock) mock := new(transactionMonitorMock)
for _, o := range opts { for _, o := range opts {
......
package transaction package transaction
import ( import (
"bytes"
"context" "context"
"errors" "errors"
"fmt" "fmt"
"math/big"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
...@@ -20,6 +22,8 @@ var ( ...@@ -20,6 +22,8 @@ var (
ErrTransactionNotFound = errors.New("transaction not found") ErrTransactionNotFound = errors.New("transaction not found")
ErrTransactionPending = errors.New("transaction in pending status") ErrTransactionPending = errors.New("transaction in pending status")
ErrTransactionSenderInvalid = errors.New("invalid transaction sender") ErrTransactionSenderInvalid = errors.New("invalid transaction sender")
ErrBlockHashMismatch = errors.New("block hash mismatch")
ErrOverlayMismatch = errors.New("overlay mismatch")
) )
func NewMatcher(backend Backend, signer types.Signer) *Matcher { func NewMatcher(backend Backend, signer types.Signer) *Matcher {
...@@ -29,24 +33,47 @@ func NewMatcher(backend Backend, signer types.Signer) *Matcher { ...@@ -29,24 +33,47 @@ func NewMatcher(backend Backend, signer types.Signer) *Matcher {
} }
} }
func (m Matcher) Matches(ctx context.Context, tx []byte, networkID uint64, senderOverlay swarm.Address) (bool, error) { func (m *Matcher) Matches(ctx context.Context, tx []byte, networkID uint64, senderOverlay swarm.Address) ([]byte, error) {
incomingTx := common.BytesToHash(tx) incomingTx := common.BytesToHash(tx)
nTx, isPending, err := m.backend.TransactionByHash(ctx, incomingTx) nTx, isPending, err := m.backend.TransactionByHash(ctx, incomingTx)
if err != nil { if err != nil {
return false, fmt.Errorf("%v: %w", err, ErrTransactionNotFound) return nil, fmt.Errorf("%v: %w", err, ErrTransactionNotFound)
} }
if isPending { if isPending {
return false, ErrTransactionPending return nil, ErrTransactionPending
} }
sender, err := types.Sender(m.signer, nTx) sender, err := types.Sender(m.signer, nTx)
if err != nil { if err != nil {
return false, fmt.Errorf("%v: %w", err, ErrTransactionSenderInvalid) return nil, fmt.Errorf("%v: %w", err, ErrTransactionSenderInvalid)
}
receipt, err := m.backend.TransactionReceipt(ctx, incomingTx)
if err != nil {
return nil, err
}
nextBlock, err := m.backend.HeaderByNumber(ctx, big.NewInt(0).Add(receipt.BlockNumber, big.NewInt(1)))
if err != nil {
return nil, err
}
receiptBlockHash := receipt.BlockHash.Bytes()
nextBlockParentHash := nextBlock.ParentHash.Bytes()
nextBlockHash := nextBlock.Hash().Bytes()
if !bytes.Equal(receiptBlockHash, nextBlockParentHash) {
return nil, fmt.Errorf("receipt hash %x does not match block's parent hash %x: %w", receiptBlockHash, nextBlockParentHash, ErrBlockHashMismatch)
} }
expectedRemoteBzzAddress := crypto.NewOverlayFromEthereumAddress(sender.Bytes(), networkID) expectedRemoteBzzAddress := crypto.NewOverlayFromEthereumAddress(sender.Bytes(), networkID, nextBlockHash)
if !expectedRemoteBzzAddress.Equal(senderOverlay) {
return nil, ErrOverlayMismatch
}
return expectedRemoteBzzAddress.Equal(senderOverlay), nil return nextBlockHash, nil
} }
...@@ -21,6 +21,7 @@ func TestMatchesSender(t *testing.T) { ...@@ -21,6 +21,7 @@ func TestMatchesSender(t *testing.T) {
suggestedGasPrice := big.NewInt(2) suggestedGasPrice := big.NewInt(2)
estimatedGasLimit := uint64(3) estimatedGasLimit := uint64(3)
nonce := uint64(2) nonce := uint64(2)
trx := common.HexToAddress("0x1").Bytes()
signedTx := types.NewTransaction(nonce, recipient, value, estimatedGasLimit, suggestedGasPrice, txData) signedTx := types.NewTransaction(nonce, recipient, value, estimatedGasLimit, suggestedGasPrice, txData)
...@@ -31,7 +32,7 @@ func TestMatchesSender(t *testing.T) { ...@@ -31,7 +32,7 @@ func TestMatchesSender(t *testing.T) {
matcher := transaction.NewMatcher(backendmock.New(txByHash), nil) matcher := transaction.NewMatcher(backendmock.New(txByHash), nil)
_, err := matcher.Matches(context.Background(), []byte("0x123"), 0, swarm.NewAddress([]byte{})) _, err := matcher.Matches(context.Background(), trx, 0, swarm.NewAddress([]byte{}))
if !errors.Is(err, transaction.ErrTransactionNotFound) { if !errors.Is(err, transaction.ErrTransactionNotFound) {
t.Fatalf("bad error type, want %v, got %v", transaction.ErrTransactionNotFound, err) t.Fatalf("bad error type, want %v, got %v", transaction.ErrTransactionNotFound, err)
} }
...@@ -44,7 +45,7 @@ func TestMatchesSender(t *testing.T) { ...@@ -44,7 +45,7 @@ func TestMatchesSender(t *testing.T) {
matcher := transaction.NewMatcher(backendmock.New(txByHash), nil) matcher := transaction.NewMatcher(backendmock.New(txByHash), nil)
_, err := matcher.Matches(context.Background(), []byte("0x123"), 0, swarm.NewAddress([]byte{})) _, err := matcher.Matches(context.Background(), trx, 0, swarm.NewAddress([]byte{}))
if !errors.Is(err, transaction.ErrTransactionPending) { if !errors.Is(err, transaction.ErrTransactionPending) {
t.Fatalf("bad error type, want %v, got %v", transaction.ErrTransactionPending, err) t.Fatalf("bad error type, want %v, got %v", transaction.ErrTransactionPending, err)
} }
...@@ -58,16 +59,19 @@ func TestMatchesSender(t *testing.T) { ...@@ -58,16 +59,19 @@ func TestMatchesSender(t *testing.T) {
signer := &mockSigner{ signer := &mockSigner{
err: errors.New("can not sign"), err: errors.New("can not sign"),
} }
matcher := transaction.NewMatcher(backendmock.New(txByHash), signer) matcher := transaction.NewMatcher(backendmock.New(txByHash), signer)
_, err := matcher.Matches(context.Background(), []byte("0x123"), 0, swarm.NewAddress([]byte{})) _, err := matcher.Matches(context.Background(), trx, 0, swarm.NewAddress([]byte{}))
if !errors.Is(err, transaction.ErrTransactionSenderInvalid) { if !errors.Is(err, transaction.ErrTransactionSenderInvalid) {
t.Fatalf("bad error type, want %v, got %v", transaction.ErrTransactionSenderInvalid, err) t.Fatalf("bad error type, want %v, got %v", transaction.ErrTransactionSenderInvalid, err)
} }
}) })
t.Run("sender does not match", func(t *testing.T) { t.Run("sender does not match", func(t *testing.T) {
block := common.HexToHash("0x1")
wrongParent := common.HexToHash("0x2")
txByHash := backendmock.WithTransactionByHashFunc(func(ctx context.Context, txHash common.Hash) (*types.Transaction, bool, error) { txByHash := backendmock.WithTransactionByHashFunc(func(ctx context.Context, txHash common.Hash) (*types.Transaction, bool, error) {
return signedTx, false, nil return signedTx, false, nil
}) })
...@@ -76,19 +80,45 @@ func TestMatchesSender(t *testing.T) { ...@@ -76,19 +80,45 @@ func TestMatchesSender(t *testing.T) {
addr: common.HexToAddress("0xabc"), addr: common.HexToAddress("0xabc"),
} }
matcher := transaction.NewMatcher(backendmock.New(txByHash), signer) trxReceipt := backendmock.WithTransactionReceiptFunc(func(ctx context.Context, txHash common.Hash) (*types.Receipt, error) {
return &types.Receipt{
BlockNumber: big.NewInt(0),
BlockHash: block,
}, nil
})
matches, err := matcher.Matches(context.Background(), []byte("0x123"), 0, swarm.NewAddress([]byte{})) headerByNum := backendmock.WithHeaderbyNumberFunc(func(ctx context.Context, number *big.Int) (*types.Header, error) {
if err != nil { return &types.Header{
t.Fatalf("expected no err, got %v", err) ParentHash: wrongParent,
} }, nil
})
if matches { matcher := transaction.NewMatcher(backendmock.New(txByHash, trxReceipt, headerByNum), signer)
t.Fatalf("expected no match, got %v", matches)
_, err := matcher.Matches(context.Background(), trx, 0, swarm.NewAddress([]byte{}))
if err == nil {
t.Fatalf("expected no match")
} }
}) })
t.Run("sender matches", func(t *testing.T) { t.Run("sender matches", func(t *testing.T) {
trxBlock := common.HexToHash("0x2")
nextBlockHeader := &types.Header{
ParentHash: trxBlock,
}
trxReceipt := backendmock.WithTransactionReceiptFunc(func(ctx context.Context, txHash common.Hash) (*types.Receipt, error) {
return &types.Receipt{
BlockNumber: big.NewInt(0),
BlockHash: trxBlock,
}, nil
})
headerByNum := backendmock.WithHeaderbyNumberFunc(func(ctx context.Context, number *big.Int) (*types.Header, error) {
return nextBlockHeader, nil
})
txByHash := backendmock.WithTransactionByHashFunc(func(ctx context.Context, txHash common.Hash) (*types.Transaction, bool, error) { txByHash := backendmock.WithTransactionByHashFunc(func(ctx context.Context, txHash common.Hash) (*types.Transaction, bool, error) {
return signedTx, false, nil return signedTx, false, nil
}) })
...@@ -97,17 +127,13 @@ func TestMatchesSender(t *testing.T) { ...@@ -97,17 +127,13 @@ func TestMatchesSender(t *testing.T) {
addr: common.HexToAddress("0xff"), addr: common.HexToAddress("0xff"),
} }
matcher := transaction.NewMatcher(backendmock.New(txByHash), signer) matcher := transaction.NewMatcher(backendmock.New(trxReceipt, headerByNum, txByHash), signer)
senderOverlay := crypto.NewOverlayFromEthereumAddress(signer.addr.Bytes(), 0) senderOverlay := crypto.NewOverlayFromEthereumAddress(signer.addr.Bytes(), 0, nextBlockHeader.Hash().Bytes())
matches, err := matcher.Matches(context.Background(), []byte("0x123"), 0, senderOverlay) _, err := matcher.Matches(context.Background(), trx, 0, senderOverlay)
if err != nil { if err != nil {
t.Fatalf("expected no err, got %v", err) t.Fatalf("expected match")
}
if !matches {
t.Fatalf("expected match, got %v", matches)
} }
}) })
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment