github.com/ethersphere/bee/v2@v2.2.0/pkg/api/rchash.go (about)

     1  // Copyright 2023 The Swarm Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  package api
     5  
     6  import (
     7  	"encoding/hex"
     8  	"net/http"
     9  	"strconv"
    10  	"time"
    11  
    12  	"github.com/ethereum/go-ethereum/common"
    13  	"github.com/ethersphere/bee/v2/pkg/jsonhttp"
    14  	"github.com/ethersphere/bee/v2/pkg/storageincentives/redistribution"
    15  	"github.com/ethersphere/bee/v2/pkg/swarm"
    16  	"github.com/gorilla/mux"
    17  )
    18  
    19  type RCHashResponse struct {
    20  	Hash     swarm.Address        `json:"hash"`
    21  	Proofs   ChunkInclusionProofs `json:"proofs"`
    22  	Duration time.Duration        `json:"duration"`
    23  }
    24  
    25  type ChunkInclusionProofs struct {
    26  	A ChunkInclusionProof `json:"proof1"`
    27  	B ChunkInclusionProof `json:"proof2"`
    28  	C ChunkInclusionProof `json:"proofLast"`
    29  }
    30  
    31  // ChunkInclusionProof structure must exactly match
    32  // corresponding structure (of the same name) in Redistribution.sol smart contract.
    33  // github.com/ethersphere/storage-incentives/blob/ph_f2/src/Redistribution.sol
    34  // github.com/ethersphere/storage-incentives/blob/master/src/Redistribution.sol (when merged to master)
    35  type ChunkInclusionProof struct {
    36  	ProofSegments  []string     `json:"proofSegments"`
    37  	ProveSegment   string       `json:"proveSegment"`
    38  	ProofSegments2 []string     `json:"proofSegments2"`
    39  	ProveSegment2  string       `json:"proveSegment2"`
    40  	ChunkSpan      uint64       `json:"chunkSpan"`
    41  	ProofSegments3 []string     `json:"proofSegments3"`
    42  	PostageProof   PostageProof `json:"postageProof"`
    43  	SocProof       []SOCProof   `json:"socProof"`
    44  }
    45  
    46  // SOCProof structure must exactly match
    47  // corresponding structure (of the same name) in Redistribution.sol smart contract.
    48  type PostageProof struct {
    49  	Signature string `json:"signature"`
    50  	PostageId string `json:"postageId"`
    51  	Index     string `json:"index"`
    52  	TimeStamp string `json:"timeStamp"`
    53  }
    54  
    55  // SOCProof structure must exactly match
    56  // corresponding structure (of the same name) in Redistribution.sol smart contract.
    57  type SOCProof struct {
    58  	Signer     string `json:"signer"`
    59  	Signature  string `json:"signature"`
    60  	Identifier string `json:"identifier"`
    61  	ChunkAddr  string `json:"chunkAddr"`
    62  }
    63  
    64  func renderChunkInclusionProofs(proofs redistribution.ChunkInclusionProofs) ChunkInclusionProofs {
    65  	return ChunkInclusionProofs{
    66  		A: renderChunkInclusionProof(proofs.A),
    67  		B: renderChunkInclusionProof(proofs.B),
    68  		C: renderChunkInclusionProof(proofs.C),
    69  	}
    70  }
    71  
    72  func renderChunkInclusionProof(proof redistribution.ChunkInclusionProof) ChunkInclusionProof {
    73  	var socProof []SOCProof
    74  	if len(proof.SocProof) == 1 {
    75  		socProof = []SOCProof{{
    76  			Signer:     hex.EncodeToString(proof.SocProof[0].Signer.Bytes()),
    77  			Signature:  hex.EncodeToString(proof.SocProof[0].Signature[:]),
    78  			Identifier: hex.EncodeToString(proof.SocProof[0].Identifier.Bytes()),
    79  			ChunkAddr:  hex.EncodeToString(proof.SocProof[0].ChunkAddr.Bytes()),
    80  		}}
    81  	}
    82  
    83  	return ChunkInclusionProof{
    84  		ProveSegment:   hex.EncodeToString(proof.ProveSegment.Bytes()),
    85  		ProofSegments:  renderCommonHash(proof.ProofSegments),
    86  		ProveSegment2:  hex.EncodeToString(proof.ProveSegment2.Bytes()),
    87  		ProofSegments2: renderCommonHash(proof.ProofSegments2),
    88  		ProofSegments3: renderCommonHash(proof.ProofSegments3),
    89  		ChunkSpan:      proof.ChunkSpan,
    90  		PostageProof: PostageProof{
    91  			Signature: hex.EncodeToString(proof.PostageProof.Signature[:]),
    92  			PostageId: hex.EncodeToString(proof.PostageProof.PostageId[:]),
    93  			Index:     strconv.FormatUint(proof.PostageProof.Index, 16),
    94  			TimeStamp: strconv.FormatUint(proof.PostageProof.TimeStamp, 16),
    95  		},
    96  		SocProof: socProof,
    97  	}
    98  }
    99  
   100  func renderCommonHash(proofSegments []common.Hash) []string {
   101  	output := make([]string, len(proofSegments))
   102  	for i, s := range proofSegments {
   103  		output[i] = hex.EncodeToString(s.Bytes())
   104  	}
   105  	return output
   106  }
   107  
   108  // This API is kept for testing the sampler. As a result, no documentation or tests are added here.
   109  func (s *Service) rchash(w http.ResponseWriter, r *http.Request) {
   110  	logger := s.logger.WithName("get_rchash").Build()
   111  
   112  	paths := struct {
   113  		Depth   uint8  `map:"depth"`
   114  		Anchor1 string `map:"anchor1,decHex" validate:"required"`
   115  		Anchor2 string `map:"anchor2,decHex" validate:"required"`
   116  	}{}
   117  	if response := s.mapStructure(mux.Vars(r), &paths); response != nil {
   118  		response("invalid path params", logger, w)
   119  		return
   120  	}
   121  
   122  	anchor1 := []byte(paths.Anchor1)
   123  
   124  	anchor2 := []byte(paths.Anchor2)
   125  
   126  	swp, err := s.redistributionAgent.SampleWithProofs(r.Context(), anchor1, anchor2, paths.Depth)
   127  	if err != nil {
   128  		logger.Error(err, "failed making sample with proofs")
   129  		jsonhttp.InternalServerError(w, "failed making sample with proofs")
   130  		return
   131  	}
   132  
   133  	resp := RCHashResponse{
   134  		Hash:     swp.Hash,
   135  		Duration: swp.Duration,
   136  		Proofs:   renderChunkInclusionProofs(swp.Proofs),
   137  	}
   138  
   139  	jsonhttp.OK(w, resp)
   140  }