diff --git a/go.mod b/go.mod index 40b0c7a4d3b..0fe90804906 100644 --- a/go.mod +++ b/go.mod @@ -10,7 +10,7 @@ require ( github.com/coreos/go-semver v0.3.0 github.com/ethereum/go-ethereum v1.12.2 github.com/ethersphere/go-price-oracle-abi v0.1.0 - github.com/ethersphere/go-storage-incentives-abi v0.6.0-rc5 + github.com/ethersphere/go-storage-incentives-abi v0.5.0 github.com/ethersphere/go-sw3-abi v0.4.0 github.com/ethersphere/langos v1.0.0 github.com/go-playground/validator/v10 v10.11.1 diff --git a/go.sum b/go.sum index ce2b77e49f3..d87cb653077 100644 --- a/go.sum +++ b/go.sum @@ -223,8 +223,8 @@ github.com/ethereum/go-ethereum v1.12.2 h1:eGHJ4ij7oyVqUQn48LBz3B7pvQ8sV0wGJiIE6 github.com/ethereum/go-ethereum v1.12.2/go.mod h1:1cRAEV+rp/xX0zraSCBnu9Py3HQ+geRMj3HdR+k0wfI= github.com/ethersphere/go-price-oracle-abi v0.1.0 h1:yg/hK8nETNvk+GEBASlbakMFv/CVp7HXiycrHw1pRV8= github.com/ethersphere/go-price-oracle-abi v0.1.0/go.mod h1:sI/Qj4/zJ23/b1enzwMMv0/hLTpPNVNacEwCWjo6yBk= -github.com/ethersphere/go-storage-incentives-abi v0.6.0-rc5 h1:JaiGMFoycByFkaCv6KFg79tfRlBJ5zY01dLWPnf48v0= -github.com/ethersphere/go-storage-incentives-abi v0.6.0-rc5/go.mod h1:SXvJVtM4sEsaSKD0jc1ClpDLw8ErPoROZDme4Wrc/Nc= +github.com/ethersphere/go-storage-incentives-abi v0.5.0 h1:dd01OZmPraCjOIiSX5FsCfFFwUR2b9PuTO/LDcYxS+s= +github.com/ethersphere/go-storage-incentives-abi v0.5.0/go.mod h1:SXvJVtM4sEsaSKD0jc1ClpDLw8ErPoROZDme4Wrc/Nc= github.com/ethersphere/go-sw3-abi v0.4.0 h1:T3ANY+ktWrPAwe2U0tZi+DILpkHzto5ym/XwV/Bbz8g= github.com/ethersphere/go-sw3-abi v0.4.0/go.mod h1:BmpsvJ8idQZdYEtWnvxA8POYQ8Rl/NhyCdF0zLMOOJU= github.com/ethersphere/langos v1.0.0 h1:NBtNKzXTTRSue95uOlzPN4py7Aofs0xWPzyj4AI1Vcc= diff --git a/pkg/api/api.go b/pkg/api/api.go index 49331689a0f..3ecea7ad000 100644 --- a/pkg/api/api.go +++ b/pkg/api/api.go @@ -10,7 +10,6 @@ import ( "context" "crypto/ecdsa" "encoding/base64" - "encoding/hex" "encoding/json" "errors" "fmt" @@ -287,10 +286,6 @@ func New( buf, err := base64.URLEncoding.DecodeString(v) return string(buf), err }, - "decHex": func(v string) (string, error) { - buf, err := hex.DecodeString(v) - return string(buf), err - }, } s.validate = validator.New() s.validate.RegisterTagNameFunc(func(fld reflect.StructField) string { diff --git a/pkg/api/api_test.go b/pkg/api/api_test.go index 21e535f10ac..8655853474f 100644 --- a/pkg/api/api_test.go +++ b/pkg/api/api_test.go @@ -57,7 +57,6 @@ import ( "github.com/ethersphere/bee/pkg/storage/inmemstore" testingc "github.com/ethersphere/bee/pkg/storage/testing" "github.com/ethersphere/bee/pkg/storageincentives" - "github.com/ethersphere/bee/pkg/storageincentives/redistribution" "github.com/ethersphere/bee/pkg/storageincentives/staking" mock2 "github.com/ethersphere/bee/pkg/storageincentives/staking/mock" mockstorer "github.com/ethersphere/bee/pkg/storer/mock" @@ -776,14 +775,14 @@ func (m *mockContract) IsWinner(context.Context) (bool, error) { return false, nil } -func (m *mockContract) Claim(context.Context, redistribution.ChunkInclusionProofs) (common.Hash, error) { +func (m *mockContract) Claim(context.Context) (common.Hash, error) { m.mtx.Lock() defer m.mtx.Unlock() m.callsList = append(m.callsList, claimCall) return common.Hash{}, nil } -func (m *mockContract) Commit(context.Context, []byte, uint32) (common.Hash, error) { +func (m *mockContract) Commit(context.Context, []byte, *big.Int) (common.Hash, error) { m.mtx.Lock() defer m.mtx.Unlock() m.callsList = append(m.callsList, commitCall) diff --git a/pkg/api/rchash.go b/pkg/api/rchash.go index ad7a25f9992..c37f642da2b 100644 --- a/pkg/api/rchash.go +++ b/pkg/api/rchash.go @@ -6,135 +6,40 @@ package api import ( "encoding/hex" "net/http" - "strconv" - "time" - "github.com/ethereum/go-ethereum/common" "github.com/ethersphere/bee/pkg/jsonhttp" - "github.com/ethersphere/bee/pkg/storageincentives/redistribution" - "github.com/ethersphere/bee/pkg/swarm" + "github.com/ethersphere/bee/pkg/storageincentives" "github.com/gorilla/mux" ) -type RCHashResponse struct { - Hash swarm.Address `json:"hash"` - Proofs ChunkInclusionProofs `json:"proofs"` - Duration time.Duration `json:"duration"` -} - -type ChunkInclusionProofs struct { - A ChunkInclusionProof `json:"proof1"` - B ChunkInclusionProof `json:"proof2"` - C ChunkInclusionProof `json:"proofLast"` -} - -// ChunkInclusionProof structure must exactly match -// corresponding structure (of the same name) in Redistribution.sol smart contract. -// github.com/ethersphere/storage-incentives/blob/ph_f2/src/Redistribution.sol -// github.com/ethersphere/storage-incentives/blob/master/src/Redistribution.sol (when merged to master) -type ChunkInclusionProof struct { - ProofSegments []string `json:"proofSegments"` - ProveSegment string `json:"proveSegment"` - ProofSegments2 []string `json:"proofSegments2"` - ProveSegment2 string `json:"proveSegment2"` - ChunkSpan uint64 `json:"chunkSpan"` - ProofSegments3 []string `json:"proofSegments3"` - PostageProof PostageProof `json:"postageProof"` - SocProof []SOCProof `json:"socProof"` -} - -// SOCProof structure must exactly match -// corresponding structure (of the same name) in Redistribution.sol smart contract. -type PostageProof struct { - Signature string `json:"signature"` - PostageId string `json:"postageId"` - Index string `json:"index"` - TimeStamp string `json:"timeStamp"` -} - -// SOCProof structure must exactly match -// corresponding structure (of the same name) in Redistribution.sol smart contract. -type SOCProof struct { - Signer string `json:"signer"` - Signature string `json:"signature"` - Identifier string `json:"identifier"` - ChunkAddr string `json:"chunkAddr"` -} - -func renderChunkInclusionProofs(proofs redistribution.ChunkInclusionProofs) ChunkInclusionProofs { - return ChunkInclusionProofs{ - A: renderChunkInclusionProof(proofs.A), - B: renderChunkInclusionProof(proofs.B), - C: renderChunkInclusionProof(proofs.C), - } -} - -func renderChunkInclusionProof(proof redistribution.ChunkInclusionProof) ChunkInclusionProof { - var socProof []SOCProof - if len(proof.SocProof) == 1 { - socProof = []SOCProof{{ - Signer: hex.EncodeToString(proof.SocProof[0].Signer.Bytes()), - Signature: hex.EncodeToString(proof.SocProof[0].Signature[:]), - Identifier: hex.EncodeToString(proof.SocProof[0].Identifier.Bytes()), - ChunkAddr: hex.EncodeToString(proof.SocProof[0].ChunkAddr.Bytes()), - }} - } - - return ChunkInclusionProof{ - ProveSegment: hex.EncodeToString(proof.ProveSegment.Bytes()), - ProofSegments: renderCommonHash(proof.ProofSegments), - ProveSegment2: hex.EncodeToString(proof.ProveSegment2.Bytes()), - ProofSegments2: renderCommonHash(proof.ProofSegments2), - ProofSegments3: renderCommonHash(proof.ProofSegments3), - ChunkSpan: proof.ChunkSpan, - PostageProof: PostageProof{ - Signature: hex.EncodeToString(proof.PostageProof.Signature[:]), - PostageId: hex.EncodeToString(proof.PostageProof.PostageId[:]), - Index: strconv.FormatUint(proof.PostageProof.Index, 16), - TimeStamp: strconv.FormatUint(proof.PostageProof.TimeStamp, 16), - }, - SocProof: socProof, - } -} - -func renderCommonHash(proofSegments []common.Hash) []string { - output := make([]string, len(proofSegments)) - for i, s := range proofSegments { - output[i] = hex.EncodeToString(s.Bytes()) - } - return output -} +type RCHashResponse storageincentives.SampleWithProofs // This API is kept for testing the sampler. As a result, no documentation or tests are added here. func (s *Service) rchash(w http.ResponseWriter, r *http.Request) { logger := s.logger.WithName("get_rchash").Build() paths := struct { - Depth uint8 `map:"depth"` - Anchor1 string `map:"anchor1,decHex" validate:"required"` - Anchor2 string `map:"anchor2,decHex" validate:"required"` + Depth *uint8 `map:"depth" validate:"required"` + Anchor1 string `map:"anchor1" validate:"required"` }{} if response := s.mapStructure(mux.Vars(r), &paths); response != nil { response("invalid path params", logger, w) return } - anchor1 := []byte(paths.Anchor1) - - anchor2 := []byte(paths.Anchor2) + anchor1, err := hex.DecodeString(paths.Anchor1) + if err != nil { + logger.Error(err, "invalid hex params") + jsonhttp.InternalServerError(w, "invalid hex params") + return + } - swp, err := s.redistributionAgent.SampleWithProofs(r.Context(), anchor1, anchor2, paths.Depth) + resp, err := s.redistributionAgent.SampleWithProofs(r.Context(), anchor1, *paths.Depth) if err != nil { logger.Error(err, "failed making sample with proofs") jsonhttp.InternalServerError(w, "failed making sample with proofs") return } - resp := RCHashResponse{ - Hash: swp.Hash, - Duration: swp.Duration, - Proofs: renderChunkInclusionProofs(swp.Proofs), - } - - jsonhttp.OK(w, resp) + jsonhttp.OK(w, RCHashResponse(resp)) } diff --git a/pkg/api/router.go b/pkg/api/router.go index 6408fd7b9af..b7f83a6623c 100644 --- a/pkg/api/router.go +++ b/pkg/api/router.go @@ -339,6 +339,12 @@ func (s *Service) mountAPI() { web.FinalHandlerFunc(s.healthHandler), )) + handle("/rchash/{depth}/{anchor1}", web.ChainHandlers( + web.FinalHandler(jsonhttp.MethodHandler{ + "GET": http.HandlerFunc(s.rchash), + }), + )) + if s.Restricted { handle("/auth", jsonhttp.MethodHandler{ "POST": web.ChainHandlers( @@ -595,10 +601,4 @@ func (s *Service) mountBusinessDebug(restricted bool) { web.FinalHandlerFunc(s.statusGetPeersHandler), ), }) - - handle("/rchash/{depth}/{anchor1}/{anchor2}", web.ChainHandlers( - web.FinalHandler(jsonhttp.MethodHandler{ - "GET": http.HandlerFunc(s.rchash), - }), - )) } diff --git a/pkg/bmt/bmt.go b/pkg/bmt/bmt.go index f314e012776..e13aa3ec1cb 100644 --- a/pkg/bmt/bmt.go +++ b/pkg/bmt/bmt.go @@ -40,19 +40,6 @@ type Hasher struct { span []byte // The span of the data subsumed under the chunk } -// NewHasher gives back an instance of a Hasher struct -func NewHasher(hasherFact func() hash.Hash) *Hasher { - conf := NewConf(hasherFact, swarm.BmtBranches, 32) - - return &Hasher{ - Conf: conf, - result: make(chan []byte), - errc: make(chan error, 1), - span: make([]byte, SpanSize), - bmt: newTree(conf.segmentSize, conf.maxSize, conf.depth, conf.hasher), - } -} - // Capacity returns the maximum amount of bytes that will be processed by this hasher implementation. // since BMT assumes a balanced binary tree, capacity it is always a power of 2 func (h *Hasher) Capacity() int { diff --git a/pkg/bmt/proof.go b/pkg/bmt/proof.go index cc59fd33766..b9a958db9ab 100644 --- a/pkg/bmt/proof.go +++ b/pkg/bmt/proof.go @@ -17,17 +17,6 @@ type Proof struct { Index int } -// Hash overrides base hash function of Hasher to fill buffer with zeros until chunk length -func (p Prover) Hash(b []byte) ([]byte, error) { - for i := p.size; i < p.maxSize; i += len(zerosection) { - _, err := p.Hasher.Write(zerosection) - if err != nil { - return nil, err - } - } - return p.Hasher.Hash(b) -} - // Proof returns the inclusion proof of the i-th data segment func (p Prover) Proof(i int) Proof { index := i @@ -47,38 +36,26 @@ func (p Prover) Proof(i int) Proof { secsize := 2 * p.segmentSize offset := i * secsize section := p.bmt.buffer[offset : offset+secsize] - segment, firstSegmentSister := section[:p.segmentSize], section[p.segmentSize:] - if index%2 != 0 { - segment, firstSegmentSister = firstSegmentSister, segment - } - sisters = append([][]byte{firstSegmentSister}, sisters...) - return Proof{segment, sisters, p.span, index} + return Proof{section, sisters, p.span, index} } // Verify returns the bmt hash obtained from the proof which can then be checked against // the BMT hash of the chunk func (p Prover) Verify(i int, proof Proof) (root []byte, err error) { - var section []byte - if i%2 == 0 { - section = append(append(section, proof.ProveSegment...), proof.ProofSegments[0]...) - } else { - section = append(append(section, proof.ProofSegments[0]...), proof.ProveSegment...) - } i = i / 2 n := p.bmt.leaves[i] - hasher := p.hasher() isLeft := n.isLeft - root, err = doHash(hasher, section) + root, err = doHash(n.hasher, proof.ProveSegment) if err != nil { return nil, err } n = n.parent - for _, sister := range proof.ProofSegments[1:] { + for _, sister := range proof.ProofSegments { if isLeft { - root, err = doHash(hasher, root, sister) + root, err = doHash(n.hasher, root, sister) } else { - root, err = doHash(hasher, sister, root) + root, err = doHash(n.hasher, sister, root) } if err != nil { return nil, err @@ -86,7 +63,7 @@ func (p Prover) Verify(i int, proof Proof) (root []byte, err error) { isLeft = n.isLeft n = n.parent } - return doHash(hasher, proof.Span, root) + return sha3hash(proof.Span, root) } func (n *node) getSister(isLeft bool) []byte { diff --git a/pkg/bmt/proof_test.go b/pkg/bmt/proof_test.go index 1b7f6d3b3dd..337b1bf3420 100644 --- a/pkg/bmt/proof_test.go +++ b/pkg/bmt/proof_test.go @@ -20,8 +20,7 @@ func TestProofCorrectness(t *testing.T) { t.Parallel() testData := []byte("hello world") - testDataPadded := make([]byte, swarm.ChunkSize) - copy(testDataPadded, testData) + testData = append(testData, make([]byte, 4096-len(testData))...) verifySegments := func(t *testing.T, exp []string, found [][]byte) { t.Helper() @@ -58,8 +57,8 @@ func TestProofCorrectness(t *testing.T) { if err != nil { t.Fatal(err) } - pr := bmt.Prover{hh} - rh, err := pr.Hash(nil) + + rh, err := hh.Hash(nil) if err != nil { t.Fatal(err) } @@ -67,10 +66,9 @@ func TestProofCorrectness(t *testing.T) { t.Run("proof for left most", func(t *testing.T) { t.Parallel() - proof := pr.Proof(0) + proof := bmt.Prover{hh}.Proof(0) expSegmentStrings := []string{ - "0000000000000000000000000000000000000000000000000000000000000000", "ad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5", "b4c11951957c6f8f642c4af61cd6b24640fec6dc7fc607ee8206a99e92410d30", "21ddb9a356815c3fac1026b6dec5df3124afbadb485c9ba5a3e3398a04b7ba85", @@ -81,7 +79,7 @@ func TestProofCorrectness(t *testing.T) { verifySegments(t, expSegmentStrings, proof.ProofSegments) - if !bytes.Equal(proof.ProveSegment, testDataPadded[:hh.Size()]) { + if !bytes.Equal(proof.ProveSegment, testData[:2*hh.Size()]) { t.Fatal("section incorrect") } @@ -93,10 +91,9 @@ func TestProofCorrectness(t *testing.T) { t.Run("proof for right most", func(t *testing.T) { t.Parallel() - proof := pr.Proof(127) + proof := bmt.Prover{hh}.Proof(127) expSegmentStrings := []string{ - "0000000000000000000000000000000000000000000000000000000000000000", "ad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5", "b4c11951957c6f8f642c4af61cd6b24640fec6dc7fc607ee8206a99e92410d30", "21ddb9a356815c3fac1026b6dec5df3124afbadb485c9ba5a3e3398a04b7ba85", @@ -107,7 +104,7 @@ func TestProofCorrectness(t *testing.T) { verifySegments(t, expSegmentStrings, proof.ProofSegments) - if !bytes.Equal(proof.ProveSegment, testDataPadded[127*hh.Size():]) { + if !bytes.Equal(proof.ProveSegment, testData[126*hh.Size():]) { t.Fatal("section incorrect") } @@ -119,10 +116,9 @@ func TestProofCorrectness(t *testing.T) { t.Run("proof for middle", func(t *testing.T) { t.Parallel() - proof := pr.Proof(64) + proof := bmt.Prover{hh}.Proof(64) expSegmentStrings := []string{ - "0000000000000000000000000000000000000000000000000000000000000000", "ad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5", "b4c11951957c6f8f642c4af61cd6b24640fec6dc7fc607ee8206a99e92410d30", "21ddb9a356815c3fac1026b6dec5df3124afbadb485c9ba5a3e3398a04b7ba85", @@ -133,7 +129,7 @@ func TestProofCorrectness(t *testing.T) { verifySegments(t, expSegmentStrings, proof.ProofSegments) - if !bytes.Equal(proof.ProveSegment, testDataPadded[64*hh.Size():65*hh.Size()]) { + if !bytes.Equal(proof.ProveSegment, testData[64*hh.Size():66*hh.Size()]) { t.Fatal("section incorrect") } @@ -146,7 +142,6 @@ func TestProofCorrectness(t *testing.T) { t.Parallel() segmentStrings := []string{ - "0000000000000000000000000000000000000000000000000000000000000000", "ad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5", "b4c11951957c6f8f642c4af61cd6b24640fec6dc7fc607ee8206a99e92410d30", "21ddb9a356815c3fac1026b6dec5df3124afbadb485c9ba5a3e3398a04b7ba85", @@ -164,9 +159,9 @@ func TestProofCorrectness(t *testing.T) { segments = append(segments, decoded) } - segment := testDataPadded[64*hh.Size() : 65*hh.Size()] + segment := testData[64*hh.Size() : 66*hh.Size()] - rootHash, err := pr.Verify(64, bmt.Proof{ + rootHash, err := bmt.Prover{hh}.Verify(64, bmt.Proof{ ProveSegment: segment, ProofSegments: segments, Span: bmt.LengthToSpan(4096), @@ -205,7 +200,6 @@ func TestProof(t *testing.T) { } rh, err := hh.Hash(nil) - pr := bmt.Prover{hh} if err != nil { t.Fatal(err) } @@ -215,7 +209,7 @@ func TestProof(t *testing.T) { t.Run(fmt.Sprintf("segmentIndex %d", i), func(t *testing.T) { t.Parallel() - proof := pr.Proof(i) + proof := bmt.Prover{hh}.Proof(i) h := pool.Get() defer pool.Put(h) diff --git a/pkg/bmt/trhasher.go b/pkg/bmt/trhasher.go new file mode 100644 index 00000000000..00df6664b85 --- /dev/null +++ b/pkg/bmt/trhasher.go @@ -0,0 +1,25 @@ +// Copyright 2023 The Swarm Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package bmt + +import ( + "hash" + + "github.com/ethersphere/bee/pkg/swarm" +) + +func NewTrHasher(prefix []byte) *Hasher { + capacity := 32 + hasherFact := func() hash.Hash { return swarm.NewTrHasher(prefix) } + conf := NewConf(hasherFact, swarm.BmtBranches, capacity) + + return &Hasher{ + Conf: conf, + result: make(chan []byte), + errc: make(chan error, 1), + span: make([]byte, SpanSize), + bmt: newTree(conf.segmentSize, conf.maxSize, conf.depth, conf.hasher), + } +} diff --git a/pkg/config/chain.go b/pkg/config/chain.go index 4d7fd19e419..2fd2e6f8fe7 100644 --- a/pkg/config/chain.go +++ b/pkg/config/chain.go @@ -42,7 +42,7 @@ var ( SwarmTokenSymbol: "gBZZ", StakingAddress: common.HexToAddress(abi.TestnetStakingAddress), - PostageStampAddress: common.HexToAddress(abi.TestnetPostageStampAddress), + PostageStampAddress: common.HexToAddress(abi.TestnetPostageStampStampAddress), RedistributionAddress: common.HexToAddress(abi.TestnetRedistributionAddress), SwapPriceOracleAddress: common.HexToAddress("0x0c9de531dcb38b758fe8a2c163444a5e54ee0db2"), CurrentFactoryAddress: common.HexToAddress("0x73c412512E1cA0be3b89b77aB3466dA6A1B9d273"), @@ -51,7 +51,7 @@ var ( }, StakingABI: abi.TestnetStakingABI, - PostageStampABI: abi.TestnetPostageStampABI, + PostageStampABI: abi.TestnetPostageStampStampABI, RedistributionABI: abi.TestnetRedistributionABI, } @@ -84,7 +84,7 @@ func GetByChainID(chainID int64) (ChainConfig, bool) { NativeTokenSymbol: Testnet.NativeTokenSymbol, SwarmTokenSymbol: Testnet.SwarmTokenSymbol, StakingABI: abi.TestnetStakingABI, - PostageStampABI: abi.TestnetPostageStampABI, + PostageStampABI: abi.TestnetPostageStampStampABI, RedistributionABI: abi.TestnetRedistributionABI, }, false } diff --git a/pkg/node/node.go b/pkg/node/node.go index ddcdad37771..36fea876a8b 100644 --- a/pkg/node/node.go +++ b/pkg/node/node.go @@ -19,10 +19,12 @@ import ( "net/http" "path/filepath" "runtime" + "strings" "sync" "sync/atomic" "time" + "github.com/ethereum/go-ethereum/accounts/abi" "github.com/ethereum/go-ethereum/common" "github.com/ethersphere/bee/pkg/accounting" "github.com/ethersphere/bee/pkg/addressbook" @@ -69,7 +71,6 @@ import ( "github.com/ethersphere/bee/pkg/topology/lightnode" "github.com/ethersphere/bee/pkg/tracing" "github.com/ethersphere/bee/pkg/transaction" - "github.com/ethersphere/bee/pkg/util/abiutil" "github.com/ethersphere/bee/pkg/util/ioutil" "github.com/ethersphere/bee/pkg/util/nbhdutil" "github.com/ethersphere/bee/pkg/util/syncutil" @@ -680,7 +681,10 @@ func NewBee( return nil, errors.New("no known postage stamp addresses for this network") } - postageStampContractABI := abiutil.MustParseABI(chainCfg.PostageStampABI) + postageStampContractABI, err := abi.JSON(strings.NewReader(chainCfg.PostageStampABI)) + if err != nil { + return nil, fmt.Errorf("unable to parse postage stamp ABI: %w", err) + } bzzTokenAddress, err := postagecontract.LookupERC20Address(ctx, transactionService, postageStampContractAddress, postageStampContractABI, chainEnabled) if err != nil { @@ -1028,7 +1032,11 @@ func NewBee( stakingContractAddress = common.HexToAddress(o.StakingContractAddress) } - stakingContract := staking.New(swarmAddress, overlayEthAddress, stakingContractAddress, abiutil.MustParseABI(chainCfg.StakingABI), bzzTokenAddress, transactionService, common.BytesToHash(nonce)) + stakingContractABI, err := abi.JSON(strings.NewReader(chainCfg.StakingABI)) + if err != nil { + return nil, fmt.Errorf("unable to parse staking ABI: %w", err) + } + stakingContract := staking.New(swarmAddress, overlayEthAddress, stakingContractAddress, stakingContractABI, bzzTokenAddress, transactionService, common.BytesToHash(nonce)) var ( pullerService *puller.Puller @@ -1051,12 +1059,16 @@ func NewBee( } redistributionContractAddress = common.HexToAddress(o.RedistributionContractAddress) } + redistributionContractABI, err := abi.JSON(strings.NewReader(chainCfg.RedistributionABI)) + if err != nil { + return nil, fmt.Errorf("unable to parse redistribution ABI: %w", err) + } isFullySynced := func() bool { return localStore.ReserveSize() >= reserveTreshold && pullerService.SyncRate() == 0 } - redistributionContract := redistribution.New(swarmAddress, logger, transactionService, redistributionContractAddress, abiutil.MustParseABI(chainCfg.RedistributionABI)) + redistributionContract := redistribution.New(swarmAddress, logger, transactionService, redistributionContractAddress, redistributionContractABI) agent, err = storageincentives.New( swarmAddress, overlayEthAddress, diff --git a/pkg/postage/postagecontract/contract.go b/pkg/postage/postagecontract/contract.go index 234cc4afdd8..94c3dc99061 100644 --- a/pkg/postage/postagecontract/contract.go +++ b/pkg/postage/postagecontract/contract.go @@ -148,36 +148,25 @@ func (c *postageContract) expireLimitedBatches(ctx context.Context, count *big.I return nil } -func (c *postageContract) sendApproveTransaction(ctx context.Context, amount *big.Int) (receipt *types.Receipt, err error) { +func (c *postageContract) sendApproveTransaction(ctx context.Context, amount *big.Int) (*types.Receipt, error) { callData, err := erc20ABI.Pack("approve", c.postageStampContractAddress, amount) if err != nil { return nil, err } - request := &transaction.TxRequest{ + txHash, err := c.transactionService.Send(ctx, &transaction.TxRequest{ To: &c.bzzTokenAddress, Data: callData, GasPrice: sctx.GetGasPrice(ctx), GasLimit: 65000, Value: big.NewInt(0), Description: approveDescription, - } - - defer func() { - err = c.transactionService.UnwrapABIError( - ctx, - request, - err, - c.postageStampContractABI.Errors, - ) - }() - - txHash, err := c.transactionService.Send(ctx, request, transaction.DefaultTipBoostPercent) + }, transaction.DefaultTipBoostPercent) if err != nil { return nil, err } - receipt, err = c.transactionService.WaitForReceipt(ctx, txHash) + receipt, err := c.transactionService.WaitForReceipt(ctx, txHash) if err != nil { return nil, err } @@ -189,7 +178,7 @@ func (c *postageContract) sendApproveTransaction(ctx context.Context, amount *bi return receipt, nil } -func (c *postageContract) sendTransaction(ctx context.Context, callData []byte, desc string) (receipt *types.Receipt, err error) { +func (c *postageContract) sendTransaction(ctx context.Context, callData []byte, desc string) (*types.Receipt, error) { request := &transaction.TxRequest{ To: &c.postageStampContractAddress, Data: callData, @@ -199,27 +188,24 @@ func (c *postageContract) sendTransaction(ctx context.Context, callData []byte, Description: desc, } - defer func() { - err = c.transactionService.UnwrapABIError( - ctx, - request, - err, - c.postageStampContractABI.Errors, - ) - }() - txHash, err := c.transactionService.Send(ctx, request, transaction.DefaultTipBoostPercent) if err != nil { return nil, err } - receipt, err = c.transactionService.WaitForReceipt(ctx, txHash) + receipt, err := c.transactionService.WaitForReceipt(ctx, txHash) if err != nil { return nil, err } if receipt.Status == 0 { - return nil, transaction.ErrTransactionReverted + err := transaction.ErrTransactionReverted + if res, cErr := c.transactionService.Call(ctx, request); cErr == nil { + if reason, uErr := abi.UnpackRevert(res); uErr == nil { + err = fmt.Errorf("%w: reason: %s", err, reason) + } + } + return nil, err } return receipt, nil diff --git a/pkg/postage/stamp.go b/pkg/postage/stamp.go index 4fff65797ad..7d65f4eee5b 100644 --- a/pkg/postage/stamp.go +++ b/pkg/postage/stamp.go @@ -6,7 +6,6 @@ package postage import ( "bytes" - "encoding/json" "errors" "fmt" @@ -119,35 +118,6 @@ func (s *Stamp) UnmarshalBinary(buf []byte) error { return nil } -type stampJson struct { - BatchID []byte `json:"batchID"` - Index []byte `json:"index"` - Timestamp []byte `json:"timestamp"` - Sig []byte `json:"sig"` -} - -func (s *Stamp) MarshalJSON() ([]byte, error) { - return json.Marshal(&stampJson{ - s.batchID, - s.index, - s.timestamp, - s.sig, - }) -} - -func (a *Stamp) UnmarshalJSON(b []byte) error { - v := &stampJson{} - err := json.Unmarshal(b, v) - if err != nil { - return err - } - a.batchID = v.BatchID - a.index = v.Index - a.timestamp = v.Timestamp - a.sig = v.Sig - return nil -} - // ToSignDigest creates a digest to represent the stamp which is to be signed by the owner. func ToSignDigest(addr, batchId, index, timestamp []byte) ([]byte, error) { h := swarm.NewHasher() diff --git a/pkg/postage/stamp_test.go b/pkg/postage/stamp_test.go index ab98a197349..f791d8e7fe6 100644 --- a/pkg/postage/stamp_test.go +++ b/pkg/postage/stamp_test.go @@ -6,7 +6,6 @@ package postage_test import ( "bytes" - "encoding/json" "math/big" "testing" @@ -32,24 +31,6 @@ func TestStampMarshalling(t *testing.T) { compareStamps(t, sExp, s) } -// TestStampMarshalling tests the idempotence of binary marshal/unmarshals for Stamps. -func TestStampJsonMarshalling(t *testing.T) { - sExp := postagetesting.MustNewStamp() - - b, err := json.Marshal(sExp) - if err != nil { - t.Fatal(err) - } - - s := postage.NewStamp(nil, nil, nil, nil) - err = json.Unmarshal(b, s) - if err != nil { - t.Fatal(err) - } - - compareStamps(t, sExp, s) -} - func compareStamps(t *testing.T, s1, s2 *postage.Stamp) { t.Helper() diff --git a/pkg/pusher/pusher.go b/pkg/pusher/pusher.go index f7abbe66d2c..2fff5739af2 100644 --- a/pkg/pusher/pusher.go +++ b/pkg/pusher/pusher.go @@ -287,7 +287,7 @@ func (s *Service) pushDeferred(ctx context.Context, logger log.Logger, op *Op) ( } case err == nil: if err := s.checkReceipt(receipt, loggerV1); err != nil { - loggerV1.Error(err, "pusher: failed checking receipt", "chunk_address", op.Chunk.Address()) + loggerV1.Error(err, "pusher: failed checking receipt") return true, err } if err := s.storer.Report(ctx, op.Chunk, storage.ChunkSynced); err != nil { @@ -341,7 +341,7 @@ func (s *Service) pushDirect(ctx context.Context, logger log.Logger, op *Op) err case err == nil: err = s.checkReceipt(receipt, loggerV1) if err != nil { - loggerV1.Error(err, "pusher: failed checking receipt", "chunk_address", op.Chunk.Address()) + loggerV1.Error(err, "pusher: failed checking receipt") } default: loggerV1.Error(err, "pusher: failed PushChunkToClosest") diff --git a/pkg/storageincentives/agent.go b/pkg/storageincentives/agent.go index 51a62393a8c..3a6ba36074a 100644 --- a/pkg/storageincentives/agent.go +++ b/pkg/storageincentives/agent.go @@ -24,7 +24,7 @@ import ( "github.com/ethersphere/bee/pkg/storage" "github.com/ethersphere/bee/pkg/storageincentives/redistribution" "github.com/ethersphere/bee/pkg/storageincentives/staking" - "github.com/ethersphere/bee/pkg/storer" + storer "github.com/ethersphere/bee/pkg/storer" "github.com/ethersphere/bee/pkg/swarm" "github.com/ethersphere/bee/pkg/transaction" ) @@ -131,7 +131,7 @@ func (a *Agent) start(blockTime time.Duration, blocksPerRound, blocksPerPhase ui phaseEvents := newEvents() defer phaseEvents.Close() - logErr := func(phase PhaseType, round uint64, err error) { + logPhaseResult := func(phase PhaseType, round uint64, err error) { if err != nil { a.logger.Error(err, "phase failed", "phase", phase, "round", round) } @@ -142,13 +142,13 @@ func (a *Agent) start(blockTime time.Duration, blocksPerRound, blocksPerPhase ui round, _ := a.state.currentRoundAndPhase() err := a.handleCommit(ctx, round) - logErr(commit, round, err) + logPhaseResult(commit, round, err) }) phaseEvents.On(reveal, func(ctx context.Context) { phaseEvents.Cancel(commit, sample) round, _ := a.state.currentRoundAndPhase() - logErr(reveal, round, a.handleReveal(ctx, round)) + logPhaseResult(reveal, round, a.handleReveal(ctx, round)) }) phaseEvents.On(claim, func(ctx context.Context) { @@ -156,13 +156,13 @@ func (a *Agent) start(blockTime time.Duration, blocksPerRound, blocksPerPhase ui phaseEvents.Publish(sample) round, _ := a.state.currentRoundAndPhase() - logErr(claim, round, a.handleClaim(ctx, round)) + logPhaseResult(claim, round, a.handleClaim(ctx, round)) }) phaseEvents.On(sample, func(ctx context.Context) { round, _ := a.state.currentRoundAndPhase() isPhasePlayed, err := a.handleSample(ctx, round) - logErr(sample, round, err) + logPhaseResult(sample, round, err) // Sample handled could potentially take long time, therefore it could overlap with commit // phase of next round. When that case happens commit event needs to be triggered once more @@ -353,22 +353,7 @@ func (a *Agent) handleClaim(ctx context.Context, round uint64) error { a.logger.Info("could not set balance", "err", err) } - sampleData, exists := a.state.SampleData(round - 1) - if !exists { - return fmt.Errorf("sample not found") - } - - anchor2, err := a.contract.ReserveSalt(ctx) - if err != nil { - a.logger.Info("failed getting anchor after second reveal", "err", err) - } - - proofs, err := makeInclusionProofs(sampleData.ReserveSampleItems, sampleData.Anchor1, anchor2) - if err != nil { - return fmt.Errorf("making inclusion proofs: %w", err) - } - - txHash, err := a.contract.Claim(ctx, proofs) + txHash, err := a.contract.Claim(ctx) if err != nil { a.metrics.ErrClaim.Inc() return fmt.Errorf("claiming win: %w", err) @@ -433,12 +418,10 @@ func (a *Agent) handleSample(ctx context.Context, round uint64) (bool, error) { if err != nil { return false, err } - dur := time.Since(now) - a.metrics.SampleDuration.Set(dur.Seconds()) a.logger.Info("produced sample", "hash", sample.ReserveSampleHash, "radius", sample.StorageRadius, "round", round) - a.state.SetSampleData(round, sample, dur) + a.state.SetSampleData(round, sample, time.Since(now)) return true, nil } @@ -454,10 +437,12 @@ func (a *Agent) makeSample(ctx context.Context, storageRadius uint8) (SampleData return SampleData{}, err } + t := time.Now() rSample, err := a.store.ReserveSample(ctx, salt, storageRadius, uint64(timeLimiter), a.minBatchBalance()) if err != nil { return SampleData{}, err } + a.metrics.SampleDuration.Set(time.Since(t).Seconds()) sampleHash, err := sampleHash(rSample.Items) if err != nil { @@ -465,10 +450,8 @@ func (a *Agent) makeSample(ctx context.Context, storageRadius uint8) (SampleData } sample := SampleData{ - Anchor1: salt, - ReserveSampleItems: rSample.Items, - ReserveSampleHash: sampleHash, - StorageRadius: storageRadius, + ReserveSampleHash: sampleHash, + StorageRadius: storageRadius, } return sample, nil @@ -510,7 +493,7 @@ func (a *Agent) commit(ctx context.Context, sample SampleData, round uint64) err return err } - txHash, err := a.contract.Commit(ctx, obfuscatedHash, uint32(round)) + txHash, err := a.contract.Commit(ctx, obfuscatedHash, big.NewInt(int64(round))) if err != nil { a.metrics.ErrCommit.Inc() return err @@ -555,16 +538,14 @@ func (a *Agent) Status() (*Status, error) { } type SampleWithProofs struct { - Hash swarm.Address `json:"hash"` - Proofs redistribution.ChunkInclusionProofs `json:"proofs"` - Duration time.Duration `json:"duration"` + Items []storer.SampleItem + Hash swarm.Address + Duration time.Duration } -// SampleWithProofs is called only by rchash API func (a *Agent) SampleWithProofs( ctx context.Context, anchor1 []byte, - anchor2 []byte, storageRadius uint8, ) (SampleWithProofs, error) { sampleStartTime := time.Now() @@ -581,17 +562,12 @@ func (a *Agent) SampleWithProofs( hash, err := sampleHash(rSample.Items) if err != nil { - return SampleWithProofs{}, fmt.Errorf("sample hash: %w", err) - } - - proofs, err := makeInclusionProofs(rSample.Items, anchor1, anchor2) - if err != nil { - return SampleWithProofs{}, fmt.Errorf("make proofs: %w", err) + return SampleWithProofs{}, fmt.Errorf("sample hash: %w:", err) } return SampleWithProofs{ + Items: rSample.Items, Hash: hash, - Proofs: proofs, Duration: time.Since(sampleStartTime), }, nil } diff --git a/pkg/storageincentives/agent_test.go b/pkg/storageincentives/agent_test.go index 70ec3193975..5d7ca5ffe90 100644 --- a/pkg/storageincentives/agent_test.go +++ b/pkg/storageincentives/agent_test.go @@ -276,14 +276,14 @@ func (m *mockContract) IsWinner(context.Context) (bool, error) { return false, nil } -func (m *mockContract) Claim(context.Context, redistribution.ChunkInclusionProofs) (common.Hash, error) { +func (m *mockContract) Claim(context.Context) (common.Hash, error) { m.mtx.Lock() defer m.mtx.Unlock() m.callsList = append(m.callsList, claimCall) return common.Hash{}, nil } -func (m *mockContract) Commit(context.Context, []byte, uint32) (common.Hash, error) { +func (m *mockContract) Commit(context.Context, []byte, *big.Int) (common.Hash, error) { m.mtx.Lock() defer m.mtx.Unlock() m.callsList = append(m.callsList, commitCall) diff --git a/pkg/storageincentives/export_test.go b/pkg/storageincentives/export_test.go index f617501ba29..8c26fc1761c 100644 --- a/pkg/storageincentives/export_test.go +++ b/pkg/storageincentives/export_test.go @@ -5,7 +5,6 @@ package storageincentives var ( - NewEvents = newEvents - SampleChunk = sampleChunk - MakeInclusionProofs = makeInclusionProofs + NewEvents = newEvents + SampleChunk = sampleChunk ) diff --git a/pkg/storageincentives/proof.go b/pkg/storageincentives/proof.go index ccc04cd935b..6415dd51af6 100644 --- a/pkg/storageincentives/proof.go +++ b/pkg/storageincentives/proof.go @@ -5,196 +5,12 @@ package storageincentives import ( - "errors" - "fmt" - "hash" - "math/big" - - "github.com/ethersphere/bee/pkg/bmt" "github.com/ethersphere/bee/pkg/bmtpool" "github.com/ethersphere/bee/pkg/cac" - "github.com/ethersphere/bee/pkg/soc" - "github.com/ethersphere/bee/pkg/storageincentives/redistribution" storer "github.com/ethersphere/bee/pkg/storer" "github.com/ethersphere/bee/pkg/swarm" ) -var errProofCreation = errors.New("reserve commitment hasher: failure in proof creation") - -// spanOffset returns the byte index of chunkdata where the spansize starts -func spanOffset(sampleItem storer.SampleItem) uint8 { - ch := swarm.NewChunk(sampleItem.ChunkAddress, sampleItem.ChunkData) - if soc.Valid(ch) { - return swarm.HashSize + swarm.SocSignatureSize - } - - return 0 -} - -// makeInclusionProofs creates transaction data for claim method. -// In the document this logic, result data, is also called Proof of entitlement (POE). -func makeInclusionProofs( - reserveSampleItems []storer.SampleItem, - anchor1 []byte, - anchor2 []byte, -) (redistribution.ChunkInclusionProofs, error) { - if len(reserveSampleItems) != storer.SampleSize { - return redistribution.ChunkInclusionProofs{}, fmt.Errorf("reserve sample items should have %d elements", storer.SampleSize) - } - if len(anchor1) == 0 { - return redistribution.ChunkInclusionProofs{}, errors.New("anchor1 is not set") - } - if len(anchor2) == 0 { - return redistribution.ChunkInclusionProofs{}, errors.New("anchor2 is not set") - } - - require3 := storer.SampleSize - 1 - require1 := new(big.Int).Mod(new(big.Int).SetBytes(anchor2), big.NewInt(int64(require3))).Uint64() - require2 := new(big.Int).Mod(new(big.Int).SetBytes(anchor2), big.NewInt(int64(require3-1))).Uint64() - if require2 >= require1 { - require2++ - } - - prefixHasherFactory := func() hash.Hash { - return swarm.NewPrefixHasher(anchor1) - } - prefixHasherPool := bmt.NewPool(bmt.NewConf(prefixHasherFactory, swarm.BmtBranches, 8)) - - // Sample chunk proofs - rccontent := bmt.Prover{Hasher: bmtpool.Get()} - rccontent.SetHeaderInt64(swarm.HashSize * storer.SampleSize * 2) - rsc, err := sampleChunk(reserveSampleItems) - if err != nil { - return redistribution.ChunkInclusionProofs{}, errProofCreation - } - rscData := rsc.Data() - _, err = rccontent.Write(rscData[swarm.SpanSize:]) - if err != nil { - return redistribution.ChunkInclusionProofs{}, errProofCreation - } - _, err = rccontent.Hash(nil) - if err != nil { - return redistribution.ChunkInclusionProofs{}, errProofCreation - } - proof1p1 := rccontent.Proof(int(require1) * 2) - proof2p1 := rccontent.Proof(int(require2) * 2) - proofLastp1 := rccontent.Proof(require3 * 2) - bmtpool.Put(rccontent.Hasher) - - // Witness1 proofs - segmentIndex := int(new(big.Int).Mod(new(big.Int).SetBytes(anchor2), big.NewInt(int64(128))).Uint64()) - // OG chunk proof - chunk1Content := bmt.Prover{Hasher: bmtpool.Get()} - chunk1Offset := spanOffset(reserveSampleItems[require1]) - chunk1Content.SetHeader(reserveSampleItems[require1].ChunkData[chunk1Offset : chunk1Offset+swarm.SpanSize]) - chunk1ContentPayload := reserveSampleItems[require1].ChunkData[chunk1Offset+swarm.SpanSize:] - _, err = chunk1Content.Write(chunk1ContentPayload) - if err != nil { - return redistribution.ChunkInclusionProofs{}, errProofCreation - } - _, err = chunk1Content.Hash(nil) - if err != nil { - return redistribution.ChunkInclusionProofs{}, errProofCreation - } - proof1p2 := chunk1Content.Proof(segmentIndex) - // TR chunk proof - chunk1TrContent := bmt.Prover{Hasher: prefixHasherPool.Get()} - chunk1TrContent.SetHeader(reserveSampleItems[require1].ChunkData[chunk1Offset : chunk1Offset+swarm.SpanSize]) - _, err = chunk1TrContent.Write(chunk1ContentPayload) - if err != nil { - return redistribution.ChunkInclusionProofs{}, errProofCreation - } - _, err = chunk1TrContent.Hash(nil) - if err != nil { - return redistribution.ChunkInclusionProofs{}, errProofCreation - } - proof1p3 := chunk1TrContent.Proof(segmentIndex) - // cleanup - bmtpool.Put(chunk1Content.Hasher) - prefixHasherPool.Put(chunk1TrContent.Hasher) - - // Witness2 proofs - // OG Chunk proof - chunk2Offset := spanOffset(reserveSampleItems[require2]) - chunk2Content := bmt.Prover{Hasher: bmtpool.Get()} - chunk2ContentPayload := reserveSampleItems[require2].ChunkData[chunk2Offset+swarm.SpanSize:] - chunk2Content.SetHeader(reserveSampleItems[require2].ChunkData[chunk2Offset : chunk2Offset+swarm.SpanSize]) - _, err = chunk2Content.Write(chunk2ContentPayload) - if err != nil { - return redistribution.ChunkInclusionProofs{}, errProofCreation - } - _, err = chunk2Content.Hash(nil) - if err != nil { - return redistribution.ChunkInclusionProofs{}, errProofCreation - } - proof2p2 := chunk2Content.Proof(segmentIndex) - // TR Chunk proof - chunk2TrContent := bmt.Prover{Hasher: prefixHasherPool.Get()} - chunk2TrContent.SetHeader(reserveSampleItems[require2].ChunkData[chunk2Offset : chunk2Offset+swarm.SpanSize]) - _, err = chunk2TrContent.Write(chunk2ContentPayload) - if err != nil { - return redistribution.ChunkInclusionProofs{}, errProofCreation - } - _, err = chunk2TrContent.Hash(nil) - if err != nil { - return redistribution.ChunkInclusionProofs{}, errProofCreation - } - proof2p3 := chunk2TrContent.Proof(segmentIndex) - // cleanup - bmtpool.Put(chunk2Content.Hasher) - prefixHasherPool.Put(chunk2TrContent.Hasher) - - // Witness3 proofs - // OG Chunk proof - chunkLastOffset := spanOffset(reserveSampleItems[require3]) - chunkLastContent := bmt.Prover{Hasher: bmtpool.Get()} - chunkLastContent.SetHeader(reserveSampleItems[require3].ChunkData[chunkLastOffset : chunkLastOffset+swarm.SpanSize]) - chunkLastContentPayload := reserveSampleItems[require3].ChunkData[chunkLastOffset+swarm.SpanSize:] - _, err = chunkLastContent.Write(chunkLastContentPayload) - if err != nil { - return redistribution.ChunkInclusionProofs{}, errProofCreation - } - _, err = chunkLastContent.Hash(nil) - if err != nil { - return redistribution.ChunkInclusionProofs{}, errProofCreation - } - proofLastp2 := chunkLastContent.Proof(segmentIndex) - // TR Chunk Proof - chunkLastTrContent := bmt.Prover{Hasher: prefixHasherPool.Get()} - chunkLastTrContent.SetHeader(reserveSampleItems[require3].ChunkData[chunkLastOffset : chunkLastOffset+swarm.SpanSize]) - _, err = chunkLastTrContent.Write(chunkLastContentPayload) - if err != nil { - return redistribution.ChunkInclusionProofs{}, errProofCreation - } - _, err = chunkLastTrContent.Hash(nil) - if err != nil { - return redistribution.ChunkInclusionProofs{}, errProofCreation - } - proofLastp3 := chunkLastTrContent.Proof(segmentIndex) - // cleanup - bmtpool.Put(chunkLastContent.Hasher) - prefixHasherPool.Put(chunkLastTrContent.Hasher) - - // map to output and add SOC related data if it is necessary - A, err := redistribution.NewChunkInclusionProof(proof1p1, proof1p2, proof1p3, reserveSampleItems[require1]) - if err != nil { - return redistribution.ChunkInclusionProofs{}, err - } - B, err := redistribution.NewChunkInclusionProof(proof2p1, proof2p2, proof2p3, reserveSampleItems[require2]) - if err != nil { - return redistribution.ChunkInclusionProofs{}, err - } - C, err := redistribution.NewChunkInclusionProof(proofLastp1, proofLastp2, proofLastp3, reserveSampleItems[require3]) - if err != nil { - return redistribution.ChunkInclusionProofs{}, err - } - return redistribution.ChunkInclusionProofs{ - A: A, - B: B, - C: C, - }, nil -} - func sampleChunk(items []storer.SampleItem) (swarm.Chunk, error) { contentSize := len(items) * 2 * swarm.HashSize @@ -211,9 +27,23 @@ func sampleChunk(items []storer.SampleItem) (swarm.Chunk, error) { } func sampleHash(items []storer.SampleItem) (swarm.Address, error) { - ch, err := sampleChunk(items) - if err != nil { - return swarm.ZeroAddress, err + hasher := bmtpool.Get() + defer bmtpool.Put(hasher) + + for _, s := range items { + _, err := hasher.Write(s.TransformedAddress.Bytes()) + if err != nil { + return swarm.ZeroAddress, err + } } - return ch.Address(), nil + hash := hasher.Sum(nil) + + return swarm.NewAddress(hash), nil + + // PH4_Logic: + // ch, err := sampleChunk(items) + // if err != nil { + // return swarm.ZeroAddress, err + // } + // return ch.Address(), nil } diff --git a/pkg/storageincentives/proof_test.go b/pkg/storageincentives/proof_test.go index 9ee3745e1af..36350c2af2c 100644 --- a/pkg/storageincentives/proof_test.go +++ b/pkg/storageincentives/proof_test.go @@ -6,157 +6,20 @@ package storageincentives_test import ( "bytes" - _ "embed" - "encoding/json" - "fmt" - "math/big" "testing" - "github.com/ethersphere/bee/pkg/cac" - "github.com/ethersphere/bee/pkg/crypto" - "github.com/ethersphere/bee/pkg/postage" - postagetesting "github.com/ethersphere/bee/pkg/postage/testing" - "github.com/ethersphere/bee/pkg/soc" "github.com/ethersphere/bee/pkg/storageincentives" - "github.com/ethersphere/bee/pkg/storageincentives/redistribution" storer "github.com/ethersphere/bee/pkg/storer" "github.com/ethersphere/bee/pkg/swarm" - "github.com/ethersphere/bee/pkg/util/testutil" - "github.com/google/go-cmp/cmp" ) -// Test asserts valid case for MakeInclusionProofs. -func TestMakeInclusionProofs(t *testing.T) { - t.Parallel() - - anchor := testutil.RandBytes(t, 1) - sample := storer.RandSample(t, anchor) - - _, err := storageincentives.MakeInclusionProofs(sample.Items, anchor, anchor) - if err != nil { - t.Fatal(err) - } -} - -//go:embed testdata/inclusion-proofs.json -var testData []byte - -// Test asserts that MakeInclusionProofs will generate the same -// output for given sample. -func TestMakeInclusionProofsRegression(t *testing.T) { - t.Parallel() - - const sampleSize = 16 - - keyRaw := `00000000000000000000000000000000` - privKey, err := crypto.DecodeSecp256k1PrivateKey([]byte(keyRaw)) - if err != nil { - t.Fatal(err) - } - signer := crypto.NewDefaultSigner(privKey) - - stampID, _ := crypto.LegacyKeccak256([]byte("The Inverted Jenny")) - index := []byte{0, 0, 0, 0, 0, 8, 3, 3} - timestamp := []byte{0, 0, 0, 0, 0, 3, 3, 8} - stamper := func(addr swarm.Address) *postage.Stamp { - sig := postagetesting.MustNewValidSignature(signer, addr, stampID, index, timestamp) - return postage.NewStamp(stampID, index, timestamp, sig) - } - - anchor1 := big.NewInt(100).Bytes() - anchor2 := big.NewInt(30).Bytes() // this anchor will pick chunks 3, 6, 15 - - // generate chunks that will be used as sample - sampleChunks := make([]swarm.Chunk, 0, sampleSize) - for i := 0; i < sampleSize; i++ { - ch, err := cac.New([]byte(fmt.Sprintf("Unstoppable data! Chunk #%d", i+1))) - if err != nil { - t.Fatal(err) - } - - if i%2 == 0 { - id, err := crypto.LegacyKeccak256([]byte(fmt.Sprintf("ID #%d", i+1))) - if err != nil { - t.Fatal(err) - } - - socCh, err := soc.New(id, ch).Sign(signer) - if err != nil { - t.Fatal(err) - } - - ch = socCh - } - - ch = ch.WithStamp(stamper(ch.Address())) - - sampleChunks = append(sampleChunks, ch) - } - - // make sample from chunks - sample, err := storer.MakeSampleUsingChunks(sampleChunks, anchor1) - if err != nil { - t.Fatal(err) - } - - // assert that sample chunk hash/address does not change - sch, err := storageincentives.SampleChunk(sample.Items) - if err != nil { - t.Fatal(err) - } - if want := swarm.MustParseHexAddress("193bbea3dd0656d813c2c1e27b821f141286bbe6ab0dbf8e26fc7dd491e8f921"); !sch.Address().Equal(want) { - t.Fatalf("expecting sample chunk address %v, got %v", want, sch.Address()) - } - - // assert that inclusion proofs values does not change - proofs, err := storageincentives.MakeInclusionProofs(sample.Items, anchor1, anchor2) - if err != nil { - t.Fatal(err) - } - - var expectedProofs redistribution.ChunkInclusionProofs - - err = json.Unmarshal(testData, &expectedProofs) - if err != nil { - t.Fatal(err) - } - - if diff := cmp.Diff(proofs, expectedProofs); diff != "" { - t.Fatalf("unexpected inclusion proofs (-want +have):\n%s", diff) - } -} - -// Test asserts cases when MakeInclusionProofs should return error. -func TestMakeInclusionProofsExpectedError(t *testing.T) { - t.Parallel() - - t.Run("invalid sample length", func(t *testing.T) { - anchor := testutil.RandBytes(t, 8) - sample := storer.RandSample(t, anchor) - - _, err := storageincentives.MakeInclusionProofs(sample.Items[:1], anchor, anchor) - if err == nil { - t.Fatal("expecting error") - } - }) - - t.Run("empty anchor", func(t *testing.T) { - sample := storer.RandSample(t, []byte{}) - - _, err := storageincentives.MakeInclusionProofs(sample.Items[:1], []byte{}, []byte{}) - if err == nil { - t.Fatal("expecting error") - } - }) -} - // Tests asserts that creating sample chunk is valid for all lengths [1-MaxSampleSize] func TestSampleChunk(t *testing.T) { t.Parallel() sample := storer.RandSample(t, nil) - for i := 0; i < len(sample.Items); i++ { + for i := 1; i < len(sample.Items); i++ { items := sample.Items[:i] chunk, err := storageincentives.SampleChunk(items) @@ -177,10 +40,6 @@ func TestSampleChunk(t *testing.T) { } pos += swarm.HashSize } - - if !chunk.Address().IsValidNonEmpty() { - t.Error("address shouldn't be empty") - } } } diff --git a/pkg/storageincentives/redistribution/inclusionproof.go b/pkg/storageincentives/redistribution/inclusionproof.go deleted file mode 100644 index b786d1d3001..00000000000 --- a/pkg/storageincentives/redistribution/inclusionproof.go +++ /dev/null @@ -1,105 +0,0 @@ -// Copyright 2023 The Swarm Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package redistribution - -import ( - "encoding/binary" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethersphere/bee/pkg/bmt" - "github.com/ethersphere/bee/pkg/soc" - "github.com/ethersphere/bee/pkg/storer" - "github.com/ethersphere/bee/pkg/swarm" -) - -type ChunkInclusionProofs struct { - A ChunkInclusionProof `json:"proof1"` - B ChunkInclusionProof `json:"proof2"` - C ChunkInclusionProof `json:"proofLast"` -} - -// ChunkInclusionProof structure must exactly match -// corresponding structure (of the same name) in Redistribution.sol smart contract. -// github.com/ethersphere/storage-incentives/blob/ph_f2/src/Redistribution.sol -// github.com/ethersphere/storage-incentives/blob/master/src/Redistribution.sol (when merged to master) -type ChunkInclusionProof struct { - ProofSegments []common.Hash `json:"proofSegments"` - ProveSegment common.Hash `json:"proveSegment"` - ProofSegments2 []common.Hash `json:"proofSegments2"` - ProveSegment2 common.Hash `json:"proveSegment2"` - ChunkSpan uint64 `json:"chunkSpan"` - ProofSegments3 []common.Hash `json:"proofSegments3"` - PostageProof PostageProof `json:"postageProof"` - SocProof []SOCProof `json:"socProof"` -} - -// SOCProof structure must exactly match -// corresponding structure (of the same name) in Redistribution.sol smart contract. -type PostageProof struct { - Signature []byte `json:"signature"` - PostageId common.Hash `json:"postageId"` - Index uint64 `json:"index"` - TimeStamp uint64 `json:"timeStamp"` -} - -// SOCProof structure must exactly match -// corresponding structure (of the same name) in Redistribution.sol smart contract. -type SOCProof struct { - Signer common.Address `json:"signer"` - Signature []byte `json:"signature"` - Identifier common.Hash `json:"identifier"` - ChunkAddr common.Hash `json:"chunkAddr"` -} - -// NewChunkInclusionProof transforms arguments to ChunkInclusionProof object -func NewChunkInclusionProof(proofp1, proofp2, proofp3 bmt.Proof, sampleItem storer.SampleItem) (ChunkInclusionProof, error) { - socProof, err := makeSOCProof(sampleItem) - if err != nil { - return ChunkInclusionProof{}, err - } - - return ChunkInclusionProof{ - ProofSegments: toCommonHash(proofp1.ProofSegments), - ProveSegment: common.BytesToHash(proofp1.ProveSegment), - ProofSegments2: toCommonHash(proofp2.ProofSegments), - ProveSegment2: common.BytesToHash(proofp2.ProveSegment), - ChunkSpan: binary.LittleEndian.Uint64(proofp2.Span[:swarm.SpanSize]), // should be uint64 on the other size; copied from pkg/api/bytes.go - ProofSegments3: toCommonHash(proofp3.ProofSegments), - PostageProof: PostageProof{ - Signature: sampleItem.Stamp.Sig(), - PostageId: common.BytesToHash(sampleItem.Stamp.BatchID()), - Index: binary.BigEndian.Uint64(sampleItem.Stamp.Index()), - TimeStamp: binary.BigEndian.Uint64(sampleItem.Stamp.Timestamp()), - }, - SocProof: socProof, - }, nil -} - -func toCommonHash(hashes [][]byte) []common.Hash { - output := make([]common.Hash, len(hashes)) - for i, s := range hashes { - output[i] = common.BytesToHash(s) - } - return output -} - -func makeSOCProof(sampleItem storer.SampleItem) ([]SOCProof, error) { - ch := swarm.NewChunk(sampleItem.ChunkAddress, sampleItem.ChunkData) - if !soc.Valid(ch) { - return []SOCProof{}, nil - } - - socCh, err := soc.FromChunk(ch) - if err != nil { - return []SOCProof{}, err - } - - return []SOCProof{{ - Signer: common.BytesToAddress(socCh.OwnerAddress()), - Signature: socCh.Signature(), - Identifier: common.BytesToHash(socCh.ID()), - ChunkAddr: common.BytesToHash(socCh.WrappedChunk().Address().Bytes()), - }}, nil -} diff --git a/pkg/storageincentives/redistribution/redistribution.go b/pkg/storageincentives/redistribution/redistribution.go index 8b83537cf90..d7187726b42 100644 --- a/pkg/storageincentives/redistribution/redistribution.go +++ b/pkg/storageincentives/redistribution/redistribution.go @@ -23,8 +23,8 @@ type Contract interface { ReserveSalt(context.Context) ([]byte, error) IsPlaying(context.Context, uint8) (bool, error) IsWinner(context.Context) (bool, error) - Claim(context.Context, ChunkInclusionProofs) (common.Hash, error) - Commit(context.Context, []byte, uint32) (common.Hash, error) + Claim(context.Context) (common.Hash, error) + Commit(context.Context, []byte, *big.Int) (common.Hash, error) Reveal(context.Context, uint8, []byte, []byte) (common.Hash, error) } @@ -92,8 +92,8 @@ func (c *contract) IsWinner(ctx context.Context) (isWinner bool, err error) { } // Claim sends a transaction to blockchain if a win is claimed. -func (c *contract) Claim(ctx context.Context, proofs ChunkInclusionProofs) (common.Hash, error) { - callData, err := c.incentivesContractABI.Pack("claim", proofs.A, proofs.B, proofs.C) +func (c *contract) Claim(ctx context.Context) (common.Hash, error) { + callData, err := c.incentivesContractABI.Pack("claim") if err != nil { return common.Hash{}, err } @@ -115,7 +115,7 @@ func (c *contract) Claim(ctx context.Context, proofs ChunkInclusionProofs) (comm } // Commit submits the obfusHash hash by sending a transaction to the blockchain. -func (c *contract) Commit(ctx context.Context, obfusHash []byte, round uint32) (common.Hash, error) { +func (c *contract) Commit(ctx context.Context, obfusHash []byte, round *big.Int) (common.Hash, error) { callData, err := c.incentivesContractABI.Pack("commit", common.BytesToHash(obfusHash), common.BytesToHash(c.overlay.Bytes()), round) if err != nil { return common.Hash{}, err @@ -180,17 +180,8 @@ func (c *contract) ReserveSalt(ctx context.Context) ([]byte, error) { return salt[:], nil } -func (c *contract) sendAndWait(ctx context.Context, request *transaction.TxRequest, boostPercent int) (txHash common.Hash, err error) { - defer func() { - err = c.txService.UnwrapABIError( - ctx, - request, - err, - c.incentivesContractABI.Errors, - ) - }() - - txHash, err = c.txService.Send(ctx, request, boostPercent) +func (c *contract) sendAndWait(ctx context.Context, request *transaction.TxRequest, boostPercent int) (common.Hash, error) { + txHash, err := c.txService.Send(ctx, request, boostPercent) if err != nil { return txHash, err } diff --git a/pkg/storageincentives/redistribution/redistribution_test.go b/pkg/storageincentives/redistribution/redistribution_test.go index 943d3013ba4..d47790d3d4b 100644 --- a/pkg/storageincentives/redistribution/redistribution_test.go +++ b/pkg/storageincentives/redistribution/redistribution_test.go @@ -7,7 +7,6 @@ package redistribution_test import ( "bytes" "context" - "encoding/binary" "errors" "fmt" "math/big" @@ -28,36 +27,6 @@ import ( var redistributionContractABI = abiutil.MustParseABI(chaincfg.Testnet.RedistributionABI) -func randChunkInclusionProof(t *testing.T) redistribution.ChunkInclusionProof { - t.Helper() - - return redistribution.ChunkInclusionProof{ - ProofSegments: []common.Hash{common.BytesToHash(testutil.RandBytes(t, 32))}, - ProveSegment: common.BytesToHash(testutil.RandBytes(t, 32)), - ProofSegments2: []common.Hash{common.BytesToHash(testutil.RandBytes(t, 32))}, - ProveSegment2: common.BytesToHash(testutil.RandBytes(t, 32)), - ProofSegments3: []common.Hash{common.BytesToHash(testutil.RandBytes(t, 32))}, - PostageProof: redistribution.PostageProof{ - Signature: testutil.RandBytes(t, 65), - PostageId: common.BytesToHash(testutil.RandBytes(t, 32)), - Index: binary.BigEndian.Uint64(testutil.RandBytes(t, 8)), - TimeStamp: binary.BigEndian.Uint64(testutil.RandBytes(t, 8)), - }, - ChunkSpan: 1, - SocProof: []redistribution.SOCProof{}, - } -} - -func randChunkInclusionProofs(t *testing.T) redistribution.ChunkInclusionProofs { - t.Helper() - - return redistribution.ChunkInclusionProofs{ - A: randChunkInclusionProof(t), - B: randChunkInclusionProof(t), - C: randChunkInclusionProof(t), - } -} - func TestRedistribution(t *testing.T) { t.Parallel() @@ -184,9 +153,7 @@ func TestRedistribution(t *testing.T) { t.Run("Claim", func(t *testing.T) { t.Parallel() - proofs := randChunkInclusionProofs(t) - - expectedCallData, err := redistributionContractABI.Pack("claim", proofs.A, proofs.B, proofs.C) + expectedCallData, err := redistributionContractABI.Pack("claim") if err != nil { t.Fatal(err) } @@ -216,7 +183,7 @@ func TestRedistribution(t *testing.T) { redistributionContractABI, ) - _, err = contract.Claim(ctx, proofs) + _, err = contract.Claim(ctx) if err != nil { t.Fatal(err) } @@ -225,8 +192,7 @@ func TestRedistribution(t *testing.T) { t.Run("Claim with tx reverted", func(t *testing.T) { t.Parallel() - proofs := randChunkInclusionProofs(t) - expectedCallData, err := redistributionContractABI.Pack("claim", proofs.A, proofs.B, proofs.C) + expectedCallData, err := redistributionContractABI.Pack("claim") if err != nil { t.Fatal(err) } @@ -256,7 +222,7 @@ func TestRedistribution(t *testing.T) { redistributionContractABI, ) - _, err = contract.Claim(ctx, proofs) + _, err = contract.Claim(ctx) if !errors.Is(err, transaction.ErrTransactionReverted) { t.Fatal(err) } @@ -267,7 +233,7 @@ func TestRedistribution(t *testing.T) { var obfus [32]byte testobfus := common.Hex2Bytes("hash") copy(obfus[:], testobfus) - expectedCallData, err := redistributionContractABI.Pack("commit", obfus, common.BytesToHash(owner.Bytes()), uint32(0)) + expectedCallData, err := redistributionContractABI.Pack("commit", obfus, common.BytesToHash(owner.Bytes()), big.NewInt(0)) if err != nil { t.Fatal(err) } @@ -297,7 +263,7 @@ func TestRedistribution(t *testing.T) { redistributionContractABI, ) - _, err = contract.Commit(ctx, testobfus, uint32(0)) + _, err = contract.Commit(ctx, testobfus, big.NewInt(0)) if err != nil { t.Fatal(err) } @@ -402,7 +368,7 @@ func TestRedistribution(t *testing.T) { t.Run("invalid call data", func(t *testing.T) { t.Parallel() - expectedCallData, err := redistributionContractABI.Pack("commit", common.BytesToHash(common.Hex2Bytes("some hash")), common.BytesToHash(common.Hex2Bytes("some address")), uint32(0)) + expectedCallData, err := redistributionContractABI.Pack("commit", common.BytesToHash(common.Hex2Bytes("some hash")), common.BytesToHash(common.Hex2Bytes("some address")), big.NewInt(0)) if err != nil { t.Fatal(err) } @@ -424,7 +390,7 @@ func TestRedistribution(t *testing.T) { redistributionContractABI, ) - _, err = contract.Commit(ctx, common.Hex2Bytes("hash"), uint32(0)) + _, err = contract.Commit(ctx, common.Hex2Bytes("hash"), big.NewInt(0)) if err == nil { t.Fatal("expected error") } diff --git a/pkg/storageincentives/redistributionstate.go b/pkg/storageincentives/redistributionstate.go index b1f4b60dd03..b61c7a5cbd2 100644 --- a/pkg/storageincentives/redistributionstate.go +++ b/pkg/storageincentives/redistributionstate.go @@ -15,7 +15,6 @@ import ( "github.com/ethersphere/bee/pkg/log" "github.com/ethersphere/bee/pkg/settlement/swap/erc20" "github.com/ethersphere/bee/pkg/storage" - storer "github.com/ethersphere/bee/pkg/storer" "github.com/ethersphere/bee/pkg/swarm" "github.com/ethersphere/bee/pkg/transaction" ) @@ -64,10 +63,8 @@ type RoundData struct { } type SampleData struct { - Anchor1 []byte - ReserveSampleItems []storer.SampleItem - ReserveSampleHash swarm.Address - StorageRadius uint8 + ReserveSampleHash swarm.Address + StorageRadius uint8 } func NewStatus() *Status { diff --git a/pkg/storageincentives/soc_mine_test.go b/pkg/storageincentives/soc_mine_test.go deleted file mode 100644 index d5b93241b21..00000000000 --- a/pkg/storageincentives/soc_mine_test.go +++ /dev/null @@ -1,201 +0,0 @@ -// Copyright 2023 The Swarm Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package storageincentives_test - -import ( - "context" - "encoding/binary" - "encoding/hex" - "fmt" - "hash" - "math/big" - "os" - "sync" - "testing" - - "github.com/ethersphere/bee/pkg/bmt" - "github.com/ethersphere/bee/pkg/cac" - "github.com/ethersphere/bee/pkg/crypto" - "github.com/ethersphere/bee/pkg/soc" - "github.com/ethersphere/bee/pkg/swarm" - "golang.org/x/sync/errgroup" -) - -// TestSocMine dumps a sample made out SOCs to upload for storage incestives - -// dump chunks - -// go test -v ./pkg/storageincentives/ -run TestSocMine -count 1 > socs.txt - -// to generate uploads using the input -// cat socs.txt | tail 19 | head 16 | perl -pne 's/([a-f0-9]+)\t([a-f0-9]+)\t([a-f0-9]+)\t([a-f0-9]+)/echo -n $4 | xxd -r -p | curl -X POST \"http:\/\/localhost:1633\/soc\/$1\/$2?sig=$3\" -H \"accept: application\/json, text\/plain, \/\" -H \"content-type: application\/octet-stream\" -H \"swarm-postage-batch-id: 14b26beca257e763609143c6b04c2c487f01a051798c535c2f542ce75a97c05f\" --data-binary \@-/' -func TestSocMine(t *testing.T) { - t.Parallel() - // the anchor used in neighbourhood selection and reserve salt for sampling - prefix, err := hex.DecodeString("3617319a054d772f909f7c479a2cebe5066e836a939412e32403c99029b92eff") - if err != nil { - t.Fatal(err) - } - // the transformed address hasher factory function - prefixhasher := func() hash.Hash { return swarm.NewPrefixHasher(prefix) } - trHasher := func() hash.Hash { return bmt.NewHasher(prefixhasher) } - // the bignum cast of the maximum sample value (upper bound on transformed addresses as a 256-bit article) - // this constant is for a minimum reserve size of 2 million chunks with sample size of 16 - // = 1.284401 * 10^71 = 1284401 + 66 0-s - mstring := "1284401" - for i := 0; i < 66; i++ { - mstring = mstring + "0" - } - n, ok := new(big.Int).SetString(mstring, 10) - if !ok { - t.Fatalf("SetString: error setting to '%s'", mstring) - } - // the filter function on the SOC address - // meant to make sure we pass check for proof of retrievability for - // a node of overlay 0x65xxx with a reserve depth of 1, i.e., - // SOC address must start with zero bit - filterSOCAddr := func(a swarm.Address) bool { - return a.Bytes()[0]&0x80 != 0x00 - } - // the filter function on the transformed address using the density estimation constant - filterTrAddr := func(a swarm.Address) (bool, error) { - m := new(big.Int).SetBytes(a.Bytes()) - return m.Cmp(n) < 0, nil - } - // setup the signer with a private key from a fixture - data, err := hex.DecodeString("634fb5a872396d9693e5c9f9d7233cfa93f395c093371017ff44aa9ae6564cdd") - if err != nil { - t.Fatal(err) - } - privKey, err := crypto.DecodeSecp256k1PrivateKey(data) - if err != nil { - t.Fatal(err) - } - signer := crypto.NewDefaultSigner(privKey) - - sampleSize := 16 - // for sanity check: given a filterSOCAddr requiring a 0 leading bit (chance of 1/2) - // we expect an overall rough 4 million chunks to be mined to create this sample - // for 8 workers that is half a million round on average per worker - err = makeChunks(t, signer, sampleSize, filterSOCAddr, filterTrAddr, trHasher) - if err != nil { - t.Fatal(err) - } -} - -func makeChunks(t *testing.T, signer crypto.Signer, sampleSize int, filterSOCAddr func(swarm.Address) bool, filterTrAddr func(swarm.Address) (bool, error), trHasher func() hash.Hash) error { - t.Helper() - - // set owner address from signer - ethAddress, err := signer.EthereumAddress() - if err != nil { - return err - } - ownerAddressBytes := ethAddress.Bytes() - - // use the same wrapped chunk for all mined SOCs - payload := []byte("foo") - ch, err := cac.New(payload) - if err != nil { - return err - } - - var done bool // to signal sampleSize number of chunks found - sampleC := make(chan *soc.SOC, 1) // channel to push resuls on - sample := make([]*soc.SOC, sampleSize) // to collect the sample - ctx, cancel := context.WithCancel(context.Background()) - eg, ectx := errgroup.WithContext(ctx) - // the main loop terminating after sampleSize SOCs have been generated - eg.Go(func() error { - defer cancel() - for i := 0; i < sampleSize; i++ { - select { - case sample[i] = <-sampleC: - case <-ectx.Done(): - return ectx.Err() - } - } - done = true - return nil - }) - - // loop to start mining workers - count := 8 // number of parallel workers - wg := sync.WaitGroup{} - for i := 0; i < count; i++ { - i := i - wg.Add(1) - eg.Go(func() (err error) { - offset := i * 4 - found := 0 - for seed := uint32(1); ; seed++ { - select { - case <-ectx.Done(): - defer wg.Done() - t.Logf("LOG quit worker: %d, rounds: %d, found: %d\n", i, seed, found) - return ectx.Err() - default: - } - id := make([]byte, 32) - binary.BigEndian.PutUint32(id[offset:], seed) - s := soc.New(id, ch) - addr, err := soc.CreateAddress(id, ownerAddressBytes) - if err != nil { - return err - } - // continue if mined SOC addr is not good - if !filterSOCAddr(addr) { - continue - } - hasher := trHasher() - data := s.WrappedChunk().Data() - hasher.(*bmt.Hasher).SetHeader(data[:8]) - _, err = hasher.Write(data[8:]) - if err != nil { - return err - } - trAddr := hasher.Sum(nil) - // hashing the transformed wrapped chunk address with the SOC address - // to arrive at a unique transformed SOC address despite identical payloads - trSocAddr, err := soc.CreateAddress(addr.Bytes(), trAddr) - if err != nil { - return err - } - ok, err := filterTrAddr(trSocAddr) - if err != nil { - return err - } - if ok { - select { - case sampleC <- s: - found++ - t.Logf("LOG worker: %d, rounds: %d, found: %d, id:%x\n", i, seed, found, id) - case <-ectx.Done(): - defer wg.Done() - t.Logf("LOG quit worker: %d, rounds: %d, found: %d\n", i, seed, found) - return ectx.Err() - } - } - } - }) - } - if err := eg.Wait(); !done && err != nil { - return err - } - wg.Wait() - for _, s := range sample { - - // signs the chunk - sch, err := s.Sign(signer) - if err != nil { - return err - } - data := sch.Data() - id, sig, payload := data[:32], data[32:97], data[97:] - fmt.Fprintf(os.Stdout, "%x\t%x\t%x\t%x\n", ownerAddressBytes, id, sig, payload) - - } - return nil -} diff --git a/pkg/storageincentives/staking/contract.go b/pkg/storageincentives/staking/contract.go index 014b1a67adc..aa05267c197 100644 --- a/pkg/storageincentives/staking/contract.go +++ b/pkg/storageincentives/staking/contract.go @@ -77,36 +77,25 @@ func New( } } -func (c *contract) sendApproveTransaction(ctx context.Context, amount *big.Int) (receipt *types.Receipt, err error) { +func (c *contract) sendApproveTransaction(ctx context.Context, amount *big.Int) (*types.Receipt, error) { callData, err := erc20ABI.Pack("approve", c.stakingContractAddress, amount) if err != nil { return nil, err } - request := &transaction.TxRequest{ + txHash, err := c.transactionService.Send(ctx, &transaction.TxRequest{ To: &c.bzzTokenAddress, Data: callData, GasPrice: sctx.GetGasPrice(ctx), GasLimit: 65000, Value: big.NewInt(0), Description: approveDescription, - } - - defer func() { - err = c.transactionService.UnwrapABIError( - ctx, - request, - err, - c.stakingContractABI.Errors, - ) - }() - - txHash, err := c.transactionService.Send(ctx, request, 0) + }, 0) if err != nil { return nil, err } - receipt, err = c.transactionService.WaitForReceipt(ctx, txHash) + receipt, err := c.transactionService.WaitForReceipt(ctx, txHash) if err != nil { return nil, err } @@ -118,7 +107,7 @@ func (c *contract) sendApproveTransaction(ctx context.Context, amount *big.Int) return receipt, nil } -func (c *contract) sendTransaction(ctx context.Context, callData []byte, desc string) (receipt *types.Receipt, err error) { +func (c *contract) sendTransaction(ctx context.Context, callData []byte, desc string) (*types.Receipt, error) { request := &transaction.TxRequest{ To: &c.stakingContractAddress, Data: callData, @@ -128,21 +117,12 @@ func (c *contract) sendTransaction(ctx context.Context, callData []byte, desc st Description: desc, } - defer func() { - err = c.transactionService.UnwrapABIError( - ctx, - request, - err, - c.stakingContractABI.Errors, - ) - }() - txHash, err := c.transactionService.Send(ctx, request, transaction.DefaultTipBoostPercent) if err != nil { return nil, err } - receipt, err = c.transactionService.WaitForReceipt(ctx, txHash) + receipt, err := c.transactionService.WaitForReceipt(ctx, txHash) if err != nil { return nil, err } diff --git a/pkg/storageincentives/testdata/inclusion-proofs.json b/pkg/storageincentives/testdata/inclusion-proofs.json deleted file mode 100644 index fe79666096e..00000000000 --- a/pkg/storageincentives/testdata/inclusion-proofs.json +++ /dev/null @@ -1,126 +0,0 @@ -{ - "proof1": { - "proofSegments": [ - "0x0875605dea48e812c9685ffba220a2b848bdbafdb95e02d087ba4a32925ea34f", - "0xf873df729270d5f4064286f3f018385a07cb4228734d8aca794299fee6e3e3e5", - "0x1fa8767fe303fe7487f5d58e4d72e5e170cf135f58a91b4fe19e4b19e5b67b5a", - "0x0f64ed713e25291e2c5a0561f584fa78c55a399e31919903d215dd622bcfd0ec", - "0x34dac0c73538614801c1ad16e272ef57f0b96a972073d15418f38daf9eb401c0", - "0x0eb01ebfc9ed27500cd4dfc979272d1f0913cc9f66540d7e8005811109e1cf2d", - "0x887c22bd8750d34016ac3c66b5ff102dacdd73f6b014e710b51e8022af9a1968" - ], - "proveSegment": "0x7133885ac59dca7b97773acb740e978d41a4af45bd563067c8a3d863578488f1", - "proofSegments2": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0xad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5", - "0xb4c11951957c6f8f642c4af61cd6b24640fec6dc7fc607ee8206a99e92410d30", - "0x21ddb9a356815c3fac1026b6dec5df3124afbadb485c9ba5a3e3398a04b7ba85", - "0x2047b070a295f8d517121d9ac9b3d5f9a944bac6cfab72dd5a7c625ab4558b0a", - "0x0eb01ebfc9ed27500cd4dfc979272d1f0913cc9f66540d7e8005811109e1cf2d", - "0x887c22bd8750d34016ac3c66b5ff102dacdd73f6b014e710b51e8022af9a1968" - ], - "proveSegment2": "0x0000000000000000000000000000000000000000000000000000000000000000", - "chunkSpan": 26, - "proofSegments3": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0xa7f526447b68535121d36909a7585c9610d4fe6d4115540464c70499b0d7136d", - "0x066dd7ce6f4f1c97e78ff1c271916db25cb06128c92f8c8520807a0fa2ba93ff", - "0xdf43c86b00db2156e769e8a8df1f08dc89ab5661c6fbaa9563f96fb9c051fc63", - "0x7327aecc9178bab420bb6fe482e07b65af69775b55666ec1ac8ab3da5bcec6dc", - "0xb68323ecaad1185a5e078f41c94c59d0b6dda5d57e109866e64d44acb8702846", - "0x478adfa93a7bb904d0aa86ff0d559f43aa915ee7865592e717b72a24452181cb" - ], - "postageProof": { - "signature": "p8jRioJ504AxaevPTlp9vdTf/vpZHqrY0c6qY2p5Otl15/exCHvOpBdlJbAALt3grL/aINvS37vnd8qziWj9xhs=", - "postageId": "0x4c8efc14c8e3cee608174f995d7afe155897bf643a31226e4f1363bc97686aef", - "index": 525059, - "timeStamp": 197384 - }, - "socProof": [ - { - "signer": "0x827b44d53df2854057713b25cdd653eb70fe36c4", - "signature": "TpV2lJM45MI/RwO/gTZyVquFmzKTT+9Nsu5Gp2v2vjVOlqxii4eEst4Lvq5ZdUaXgxktbRcFSF/Krdje3ebiqhs=", - "identifier": "0x6223cfdd75a40440ccd32d0b11b24f08562ec63b1ea3b8cb1a59dfc3e3c33595", - "chunkAddr": "0xf32442586d93d8c002372ed41fa2ea1f281f38311c161d535c3665de5d9bfd92" - } - ] - }, - "proof2": { - "proofSegments": [ - "0x463aeb4ca5f000064c082e56eba387004265d2f47bf1226ef2d86cb163bcca3a", - "0x829af58b2a2f1c6c156baa196f03be4df510a96419f2dd54c456d3da30166312", - "0xdee4815ec42efa507b79cf4eb1f272e07be1b526cbd48137a287d9e5b2b2808a", - "0x0f64ed713e25291e2c5a0561f584fa78c55a399e31919903d215dd622bcfd0ec", - "0x34dac0c73538614801c1ad16e272ef57f0b96a972073d15418f38daf9eb401c0", - "0x0eb01ebfc9ed27500cd4dfc979272d1f0913cc9f66540d7e8005811109e1cf2d", - "0x887c22bd8750d34016ac3c66b5ff102dacdd73f6b014e710b51e8022af9a1968" - ], - "proveSegment": "0x535e6df58a122a8f5e6c851c19b3e042f4cd1b5c5a8c499581c9f6d4e3509182", - "proofSegments2": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0xad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5", - "0xb4c11951957c6f8f642c4af61cd6b24640fec6dc7fc607ee8206a99e92410d30", - "0x21ddb9a356815c3fac1026b6dec5df3124afbadb485c9ba5a3e3398a04b7ba85", - "0x46f43b515833749217540ac60c79e0c6a54c73f3500850b5869b31d5c89d101f", - "0x0eb01ebfc9ed27500cd4dfc979272d1f0913cc9f66540d7e8005811109e1cf2d", - "0x887c22bd8750d34016ac3c66b5ff102dacdd73f6b014e710b51e8022af9a1968" - ], - "proveSegment2": "0x0000000000000000000000000000000000000000000000000000000000000000", - "chunkSpan": 26, - "proofSegments3": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0xa7f526447b68535121d36909a7585c9610d4fe6d4115540464c70499b0d7136d", - "0x066dd7ce6f4f1c97e78ff1c271916db25cb06128c92f8c8520807a0fa2ba93ff", - "0xdf43c86b00db2156e769e8a8df1f08dc89ab5661c6fbaa9563f96fb9c051fc63", - "0x4284c510d7d64c9e052c73bddadb1fca522fd26caf2ebf007faad50a9a0f09fa", - "0xb68323ecaad1185a5e078f41c94c59d0b6dda5d57e109866e64d44acb8702846", - "0x478adfa93a7bb904d0aa86ff0d559f43aa915ee7865592e717b72a24452181cb" - ], - "postageProof": { - "signature": "sCdPzaWeiq/+6AMCGXGnZKAXziwPQcjOtu796oBwVvYhqY/qtevzO7YGXknAUPQT7IhAsAj8Ik2ILOUkTOPgFxw=", - "postageId": "0x4c8efc14c8e3cee608174f995d7afe155897bf643a31226e4f1363bc97686aef", - "index": 525059, - "timeStamp": 197384 - }, - "socProof": [] - }, - "proofLast": { - "proofSegments": [ - "0xfee18543782df46a86f85456e62dc973a4c84369b6b1cd4f93e57fe247f9730e", - "0x23a0858ee2b8b4cb0ba66d3533f468d6b583a6b77df0cc78fc6df64dc735a917", - "0xb6bffa54dec44ad57349f9aef6cb65a1f8807f15447462ec519751220e5a5bc3", - "0x553aae9948fc13c33d8b353cf5694ecadc7c40c8316ce09cbd4d864dbb94f026", - "0xaf7db874a9b5addf602b3e899194480a32afec6d6cd4ec0fadf9e065db739dd5", - "0x0eb01ebfc9ed27500cd4dfc979272d1f0913cc9f66540d7e8005811109e1cf2d", - "0x887c22bd8750d34016ac3c66b5ff102dacdd73f6b014e710b51e8022af9a1968" - ], - "proveSegment": "0x5ba2c8b912fad4aeb4a11a960946d07b9f66bc40ac54d87224914d75f5aeea5f", - "proofSegments2": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0xad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5", - "0xb4c11951957c6f8f642c4af61cd6b24640fec6dc7fc607ee8206a99e92410d30", - "0x21ddb9a356815c3fac1026b6dec5df3124afbadb485c9ba5a3e3398a04b7ba85", - "0x7f575db255ef42dcaeb7658df9f33fe5a1aad5d41af51a72a381acea29d98a12", - "0x0eb01ebfc9ed27500cd4dfc979272d1f0913cc9f66540d7e8005811109e1cf2d", - "0x887c22bd8750d34016ac3c66b5ff102dacdd73f6b014e710b51e8022af9a1968" - ], - "proveSegment2": "0x0000000000000000000000000000000000000000000000000000000000000000", - "chunkSpan": 27, - "proofSegments3": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0xa7f526447b68535121d36909a7585c9610d4fe6d4115540464c70499b0d7136d", - "0x066dd7ce6f4f1c97e78ff1c271916db25cb06128c92f8c8520807a0fa2ba93ff", - "0xdf43c86b00db2156e769e8a8df1f08dc89ab5661c6fbaa9563f96fb9c051fc63", - "0x7683427ba0ef1fbebf97f2fc36859df88ead8123369fe38d7b767b7a7eda5294", - "0xb68323ecaad1185a5e078f41c94c59d0b6dda5d57e109866e64d44acb8702846", - "0x478adfa93a7bb904d0aa86ff0d559f43aa915ee7865592e717b72a24452181cb" - ], - "postageProof": { - "signature": "Z0fFjOhhNIbGlvW7c5PJxZCUNxlpw6Ur+vdRksYF9K18cMbnH90yDiDQBeQulO4yECwjTrRl9PX9nbYPytA1axw=", - "postageId": "0x4c8efc14c8e3cee608174f995d7afe155897bf643a31226e4f1363bc97686aef", - "index": 525059, - "timeStamp": 197384 - }, - "socProof": [] - } -} \ No newline at end of file diff --git a/pkg/storer/sample.go b/pkg/storer/sample.go index 196bb4d26a9..690e06affc3 100644 --- a/pkg/storer/sample.go +++ b/pkg/storer/sample.go @@ -7,9 +7,9 @@ package storer import ( "bytes" "context" + "crypto/hmac" "encoding/binary" "fmt" - "hash" "math/big" "sort" "sync" @@ -26,13 +26,13 @@ import ( "golang.org/x/sync/errgroup" ) -const SampleSize = 16 +const SampleSize = 8 type SampleItem struct { TransformedAddress swarm.Address ChunkAddress swarm.Address ChunkData []byte - Stamp *postage.Stamp + Stamp swarm.Stamp } type Sample struct { @@ -40,37 +40,18 @@ type Sample struct { Items []SampleItem } -// RandSample returns Sample with random values. func RandSample(t *testing.T, anchor []byte) Sample { t.Helper() - chunks := make([]swarm.Chunk, SampleSize) + hasher := bmt.NewTrHasher(anchor) + + items := make([]SampleItem, SampleSize) for i := 0; i < SampleSize; i++ { ch := chunk.GenerateTestRandomChunk() - if i%3 == 0 { - ch = chunk.GenerateTestRandomSoChunk(t, ch) - } - chunks[i] = ch - } - - sample, err := MakeSampleUsingChunks(chunks, anchor) - if err != nil { - t.Fatal(err) - } - return sample -} - -// MakeSampleUsingChunks returns Sample constructed using supplied chunks. -func MakeSampleUsingChunks(chunks []swarm.Chunk, anchor []byte) (Sample, error) { - prefixHasherFactory := func() hash.Hash { - return swarm.NewPrefixHasher(anchor) - } - items := make([]SampleItem, len(chunks)) - for i, ch := range chunks { - tr, err := transformedAddress(bmt.NewHasher(prefixHasherFactory), ch, swarm.ChunkTypeContentAddressed) + tr, err := transformedAddress(hasher, ch, swarm.ChunkTypeContentAddressed) if err != nil { - return Sample{}, err + t.Fatal(err) } items[i] = SampleItem{ @@ -85,7 +66,7 @@ func MakeSampleUsingChunks(chunks []swarm.Chunk, anchor []byte) (Sample, error) return items[i].TransformedAddress.Compare(items[j].TransformedAddress) == -1 }) - return Sample{Items: items}, nil + return Sample{Items: items} } func newStamp(s swarm.Stamp) *postage.Stamp { @@ -154,25 +135,19 @@ func (db *DB) ReserveSample( // Phase 2: Get the chunk data and calculate transformed hash sampleItemChan := make(chan SampleItem, 64) - prefixHasherFactory := func() hash.Hash { - return swarm.NewPrefixHasher(anchor) - } - const workers = 6 - for i := 0; i < workers; i++ { g.Go(func() error { wstat := SampleStats{} - hasher := bmt.NewHasher(prefixHasherFactory) defer func() { addStats(wstat) }() + hmacr := hmac.New(swarm.NewHasher, anchor) for chItem := range chunkC { // exclude chunks who's batches balance are below minimum if _, found := excludedBatchIDs[string(chItem.BatchID)]; found { wstat.BelowBalanceIgnored++ - continue } @@ -194,12 +169,16 @@ func (db *DB) ReserveSample( wstat.ChunkLoadDuration += time.Since(chunkLoadStart) - taddrStart := time.Now() - taddr, err := transformedAddress(hasher, chunk, chItem.Type) + hmacrStart := time.Now() + + hmacr.Reset() + _, err = hmacr.Write(chunk.Data()) if err != nil { return err } - wstat.TaddrDuration += time.Since(taddrStart) + taddr := swarm.NewAddress(hmacr.Sum(nil)) + + wstat.HmacrDuration += time.Since(hmacrStart) select { case sampleItemChan <- SampleItem{ @@ -243,15 +222,6 @@ func (db *DB) ReserveSample( } } - contains := func(addr swarm.Address) int { - for index, item := range sampleItems { - if item.ChunkAddress.Compare(addr) == 0 { - return index - } - } - return -1 - } - // Phase 3: Assemble the sample. Here we need to assemble only the first SampleSize // no of items from the results of the 2nd phase. // In this step stamps are loaded and validated only if chunk will be added to sample. @@ -288,14 +258,7 @@ func (db *DB) ReserveSample( stats.ValidStampDuration += time.Since(start) - item.Stamp = postage.NewStamp(stamp.BatchID(), stamp.Index(), stamp.Timestamp(), stamp.Sig()) - - // ensuring to pass the check order function of redistribution contract - if index := contains(item.TransformedAddress); index != -1 { - // replace the chunk at index - sampleItems[index] = item - continue - } + item.Stamp = stamp insert(item) stats.SampleInserts++ } @@ -396,7 +359,7 @@ type SampleStats struct { NewIgnored int64 InvalidStamp int64 BelowBalanceIgnored int64 - TaddrDuration time.Duration + HmacrDuration time.Duration ValidStampDuration time.Duration BatchesBelowValueDuration time.Duration RogueChunk int64 @@ -413,7 +376,7 @@ func (s *SampleStats) add(other SampleStats) { s.NewIgnored += other.NewIgnored s.InvalidStamp += other.InvalidStamp s.BelowBalanceIgnored += other.BelowBalanceIgnored - s.TaddrDuration += other.TaddrDuration + s.HmacrDuration += other.HmacrDuration s.ValidStampDuration += other.ValidStampDuration s.BatchesBelowValueDuration += other.BatchesBelowValueDuration s.RogueChunk += other.RogueChunk diff --git a/pkg/swarm/hasher.go b/pkg/swarm/hasher.go index b9823bb50a1..485b61ab398 100644 --- a/pkg/swarm/hasher.go +++ b/pkg/swarm/hasher.go @@ -15,15 +15,15 @@ func NewHasher() hash.Hash { return sha3.NewLegacyKeccak256() } -type PrefixHasher struct { +type trHasher struct { hash.Hash prefix []byte } -// NewPrefixHasher returns new hasher which is Keccak-256 hasher +// NewTrHasher returns new hasher which is Keccak-256 hasher // with prefix value added as initial data. -func NewPrefixHasher(prefix []byte) hash.Hash { - h := &PrefixHasher{ +func NewTrHasher(prefix []byte) hash.Hash { + h := &trHasher{ Hash: NewHasher(), prefix: prefix, } @@ -32,7 +32,7 @@ func NewPrefixHasher(prefix []byte) hash.Hash { return h } -func (h *PrefixHasher) Reset() { +func (h *trHasher) Reset() { h.Hash.Reset() _, _ = h.Write(h.prefix) } diff --git a/pkg/swarm/hasher_test.go b/pkg/swarm/hasher_test.go index 3811e09605a..bfee0a78e98 100644 --- a/pkg/swarm/hasher_test.go +++ b/pkg/swarm/hasher_test.go @@ -66,7 +66,7 @@ func TestNewTrHasher(t *testing.T) { // Run tests cases against TrHasher for _, tc := range tests { - h := swarm.NewPrefixHasher(tc.prefix) + h := swarm.NewTrHasher(tc.prefix) _, err := h.Write(tc.plaintext) if err != nil { diff --git a/pkg/transaction/mock/transaction.go b/pkg/transaction/mock/transaction.go index 7478daa63e6..f9a557f00be 100644 --- a/pkg/transaction/mock/transaction.go +++ b/pkg/transaction/mock/transaction.go @@ -97,10 +97,6 @@ func (m *transactionServiceMock) TransactionFee(ctx context.Context, txHash comm return big.NewInt(0), nil } -func (m *transactionServiceMock) UnwrapABIError(_ context.Context, _ *transaction.TxRequest, err error, _ map[string]abi.Error) error { - return err -} - // Option is the option passed to the mock Chequebook service type Option interface { apply(*transactionServiceMock) diff --git a/pkg/transaction/transaction.go b/pkg/transaction/transaction.go index 28d3912c78d..d8cb6d797d3 100644 --- a/pkg/transaction/transaction.go +++ b/pkg/transaction/transaction.go @@ -5,7 +5,6 @@ package transaction import ( - "bytes" "errors" "fmt" "io" @@ -15,7 +14,6 @@ import ( "time" "github.com/ethereum/go-ethereum" - "github.com/ethereum/go-ethereum/accounts/abi" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" "github.com/ethersphere/bee/pkg/crypto" @@ -96,9 +94,6 @@ type Service interface { CancelTransaction(ctx context.Context, originalTxHash common.Hash) (common.Hash, error) // TransactionFee retrieves the transaction fee TransactionFee(ctx context.Context, txHash common.Hash) (*big.Int, error) - // UnwrapABIError tries to unwrap the ABI error if the given error is not nil. - // The original error is wrapped together with the ABI error if it exists. - UnwrapABIError(ctx context.Context, req *TxRequest, err error, abiErrors map[string]abi.Error) error } type transactionService struct { @@ -283,8 +278,7 @@ func (t *transactionService) prepareTransaction(ctx context.Context, request *Tx Data: request.Data, }) if err != nil { - t.logger.Debug("estimage gas failed", "error", err) - gasLimit = request.MinEstimatedGasLimit + return nil, err } gasLimit += gasLimit / 4 // add 25% on top @@ -590,27 +584,3 @@ func (t *transactionService) TransactionFee(ctx context.Context, txHash common.H } return trx.Cost(), nil } - -func (t *transactionService) UnwrapABIError(ctx context.Context, req *TxRequest, err error, abiErrors map[string]abi.Error) error { - if err == nil { - return nil - } - - res, cErr := t.Call(ctx, req) - if cErr != nil { - return err - } - - if reason, uErr := abi.UnpackRevert(res); uErr == nil { - return fmt.Errorf("%w: %s", err, reason) - } - - for _, abiError := range abiErrors { - if bytes.Equal(res[:4], abiError.ID[:4]) { - //abiError.Unpack(res[4:]) - return fmt.Errorf("%w: %s", err, abiError) - } - } - - return err -} diff --git a/pkg/transaction/transaction_test.go b/pkg/transaction/transaction_test.go index 8794fd33281..60e0989a8a0 100644 --- a/pkg/transaction/transaction_test.go +++ b/pkg/transaction/transaction_test.go @@ -7,7 +7,6 @@ package transaction_test import ( "bytes" "context" - "errors" "fmt" "math/big" "testing" @@ -214,126 +213,6 @@ func TestTransactionSend(t *testing.T) { } }) - t.Run("send with estimate error", func(t *testing.T) { - t.Parallel() - - signedTx := types.NewTx(&types.DynamicFeeTx{ - ChainID: chainID, - Nonce: nonce, - To: &recipient, - Value: value, - Gas: estimatedGasLimit, - GasFeeCap: defaultGasFee, - GasTipCap: suggestedGasTip, - Data: txData, - }) - request := &transaction.TxRequest{ - To: &recipient, - Data: txData, - Value: value, - MinEstimatedGasLimit: estimatedGasLimit, - } - store := storemock.NewStateStore() - err := store.Put(nonceKey(sender), nonce) - if err != nil { - t.Fatal(err) - } - - transactionService, err := transaction.NewService(logger, - backendmock.New( - backendmock.WithSendTransactionFunc(func(ctx context.Context, tx *types.Transaction) error { - if tx != signedTx { - t.Fatal("not sending signed transaction") - } - return nil - }), - backendmock.WithEstimateGasFunc(func(ctx context.Context, call ethereum.CallMsg) (gas uint64, err error) { - return 0, errors.New("estimate failure") - }), - backendmock.WithSuggestGasPriceFunc(func(ctx context.Context) (*big.Int, error) { - return suggestedGasPrice, nil - }), - backendmock.WithPendingNonceAtFunc(func(ctx context.Context, account common.Address) (uint64, error) { - return nonce - 1, nil - }), - backendmock.WithSuggestGasTipCapFunc(func(ctx context.Context) (*big.Int, error) { - return suggestedGasTip, nil - }), - ), - signerMockForTransaction(t, signedTx, sender, chainID), - store, - chainID, - monitormock.New( - monitormock.WithWatchTransactionFunc(func(txHash common.Hash, nonce uint64) (<-chan types.Receipt, <-chan error, error) { - return nil, nil, nil - }), - ), - ) - if err != nil { - t.Fatal(err) - } - testutil.CleanupCloser(t, transactionService) - - txHash, err := transactionService.Send(context.Background(), request, 0) - if err != nil { - t.Fatal(err) - } - - if !bytes.Equal(txHash.Bytes(), signedTx.Hash().Bytes()) { - t.Fatal("returning wrong transaction hash") - } - - var storedNonce uint64 - err = store.Get(nonceKey(sender), &storedNonce) - if err != nil { - t.Fatal(err) - } - if storedNonce != nonce+1 { - t.Fatalf("nonce not stored correctly: want %d, got %d", nonce+1, storedNonce) - } - - storedTransaction, err := transactionService.StoredTransaction(txHash) - if err != nil { - t.Fatal(err) - } - - if storedTransaction.To == nil || *storedTransaction.To != recipient { - t.Fatalf("got wrong recipient in stored transaction. wanted %x, got %x", recipient, storedTransaction.To) - } - - if !bytes.Equal(storedTransaction.Data, request.Data) { - t.Fatalf("got wrong data in stored transaction. wanted %x, got %x", request.Data, storedTransaction.Data) - } - - if storedTransaction.Description != request.Description { - t.Fatalf("got wrong description in stored transaction. wanted %x, got %x", request.Description, storedTransaction.Description) - } - - if storedTransaction.GasLimit != estimatedGasLimit { - t.Fatalf("got wrong gas limit in stored transaction. wanted %d, got %d", estimatedGasLimit, storedTransaction.GasLimit) - } - - if defaultGasFee.Cmp(storedTransaction.GasPrice) != 0 { - t.Fatalf("got wrong gas price in stored transaction. wanted %d, got %d", defaultGasFee, storedTransaction.GasPrice) - } - - if storedTransaction.Nonce != nonce { - t.Fatalf("got wrong nonce in stored transaction. wanted %d, got %d", nonce, storedTransaction.Nonce) - } - - pending, err := transactionService.PendingTransactions() - if err != nil { - t.Fatal(err) - } - if len(pending) != 1 { - t.Fatalf("expected one pending transaction, got %d", len(pending)) - } - - if pending[0] != txHash { - t.Fatalf("got wrong pending transaction. wanted %x, got %x", txHash, pending[0]) - } - }) - t.Run("sendWithBoost", func(t *testing.T) { t.Parallel()