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 }