77 "os"
88 "strconv"
99 "strings"
10+ "sync"
1011 "time"
1112
1213 "github.com/celestiaorg/go-square/v3/share"
@@ -78,12 +79,12 @@ func searchCmd() *cobra.Command {
7879Starting from the given DA height, searches through a range of DA heights until it finds matching blobs.` ,
7980 Args : cobra .ExactArgs (2 ),
8081 RunE : func (cmd * cobra.Command , args []string ) error {
81- return runSearch (cmd , args , searchHeight , searchRange )
82+ return runSearch (args , searchHeight , searchRange )
8283 },
8384 }
8485
8586 cmd .Flags ().Uint64Var (& searchHeight , "target-height" , 0 , "Target blockchain height to search for (required)" )
86- cmd .Flags ().Uint64Var (& searchRange , "range" , 10 , "Number of DA heights to search" )
87+ cmd .Flags ().Uint64Var (& searchRange , "range" , 0 , "Number of DA heights to search (0 = search until found) " )
8788 cmd .MarkFlagRequired ("target-height" )
8889
8990 return cmd
@@ -115,7 +116,7 @@ func runQuery(cmd *cobra.Command, args []string) error {
115116 return queryHeight (ctx , client , height , namespace )
116117}
117118
118- func runSearch (cmd * cobra. Command , args []string , searchHeight , searchRange uint64 ) error {
119+ func runSearch (args []string , searchHeight , searchRange uint64 ) error {
119120 startHeight , err := strconv .ParseUint (args [0 ], 10 , 64 )
120121 if err != nil {
121122 return fmt .Errorf ("invalid start height: %w" , err )
@@ -135,24 +136,50 @@ func runSearch(cmd *cobra.Command, args []string, searchHeight, searchRange uint
135136 }
136137 defer closeFn ()
137138
138- ctx , cancel := context .WithTimeout (context .Background (), timeout )
139- defer cancel ()
139+ rootCtx := context .Background ()
140+ return searchForHeight (rootCtx , client , startHeight , namespace , searchHeight , searchRange )
141+ }
140142
141- return searchForHeight (ctx , client , startHeight , namespace , searchHeight , searchRange )
143+ type blobResult struct {
144+ blobData []byte
145+ found bool
146+ header * types.SignedHeader
147+ data * types.SignedData
148+ blobHeight uint64
142149}
143150
144151func searchForHeight (ctx context.Context , client * blobrpc.Client , startHeight uint64 , namespace []byte , targetHeight , searchRange uint64 ) error {
145- fmt .Printf ("Searching for height %d in DA heights %d-%d...\n " , targetHeight , startHeight , startHeight + searchRange - 1 )
146- fmt .Println ()
152+ if searchRange > 0 {
153+ fmt .Printf ("Searching for height %d in DA heights %d-%d...\n " , targetHeight , startHeight , startHeight + searchRange - 1 )
154+ } else {
155+ fmt .Printf ("Searching for height %d from DA height %d onwards...\n " , targetHeight , startHeight )
156+ }
147157
148158 ns , err := share .NewNamespaceFromBytes (namespace )
149159 if err != nil {
150160 return fmt .Errorf ("invalid namespace: %w" , err )
151161 }
152162
153163 foundBlobs := 0
154- for daHeight := startHeight ; daHeight < startHeight + searchRange ; daHeight ++ {
155- blobs , err := client .Blob .GetAll (ctx , daHeight , []share.Namespace {ns })
164+ daHeight := startHeight
165+ for {
166+ if searchRange > 0 && daHeight >= startHeight + searchRange || foundBlobs > 0 {
167+ break
168+ }
169+
170+ fmt .Printf ("Checking DA height %d...\r " , daHeight )
171+
172+ var fetchCtx context.Context
173+ var fetchCancel context.CancelFunc
174+ if timeout > 0 {
175+ fetchCtx , fetchCancel = context .WithTimeout (ctx , timeout )
176+ } else {
177+ fetchCtx , fetchCancel = ctx , func () {}
178+ }
179+
180+ blobs , err := client .Blob .GetAll (fetchCtx , daHeight , []share.Namespace {ns })
181+ fetchCancel ()
182+
156183 if err != nil {
157184 if strings .Contains (err .Error (), "future" ) {
158185 fmt .Printf ("Reached future height at DA height %d\n " , daHeight )
@@ -161,50 +188,83 @@ func searchForHeight(ctx context.Context, client *blobrpc.Client, startHeight ui
161188 continue
162189 }
163190
164- // Check each blob for the target height
165- for _ , blob := range blobs {
166- blobData := blob .Data ()
167- found := false
168- var blobHeight uint64
191+ // Process blobs in parallel
192+ results := make (chan blobResult , len (blobs ))
193+ var wg sync.WaitGroup
169194
170- // Try to decode as header first
171- if header := tryDecodeHeader (blobData ); header != nil {
172- blobHeight = header .Height ()
173- if blobHeight == targetHeight {
174- found = true
195+ for _ , blob := range blobs {
196+ wg .Add (1 )
197+ go func (b any ) {
198+ defer wg .Done ()
199+
200+ var blobData []byte
201+ switch v := b .(type ) {
202+ case interface { Data () []byte }:
203+ blobData = v .Data ()
204+ default :
205+ results <- blobResult {blobData : blobData , found : false }
206+ return
175207 }
176- } else if data := tryDecodeData (blobData ); data != nil {
177- if data .Metadata != nil {
178- blobHeight = data .Height ()
208+
209+ // Try to decode as header first
210+ if header := tryDecodeHeader (blobData ); header != nil {
211+ blobHeight := header .Height ()
179212 if blobHeight == targetHeight {
180- found = true
213+ results <- blobResult {blobData : blobData , found : true , header : header , blobHeight : blobHeight }
214+ return
181215 }
182216 }
183- }
184217
185- if found {
218+ // Try to decode as data
219+ if data := tryDecodeData (blobData ); data != nil {
220+ if data .Metadata != nil {
221+ blobHeight := data .Height ()
222+ if blobHeight == targetHeight {
223+ results <- blobResult {blobData : blobData , found : true , data : data , blobHeight : blobHeight }
224+ return
225+ }
226+ }
227+ }
228+
229+ // Not found
230+ results <- blobResult {blobData : blobData , found : false }
231+ }(blob )
232+ }
233+
234+ go func () {
235+ wg .Wait ()
236+ close (results )
237+ }()
238+
239+ // Collect results
240+ for result := range results {
241+ if result .found {
242+ fmt .Println ()
186243 foundBlobs ++
187244 fmt .Printf ("FOUND at DA Height %d - BLOB %d\n " , daHeight , foundBlobs )
188- fmt .Println (strings .Repeat ("-" , 80 ))
189- displayBlobInfo (blobData )
245+ fmt .Println (strings .Repeat ("-" , 50 ))
246+ displayBlobInfo (result . blobData )
190247
191248 // Display the decoded content
192- if header := tryDecodeHeader ( blobData ); header != nil {
249+ if result . header != nil {
193250 printTypeHeader ("SignedHeader" , "" )
194- displayHeader (header )
195- } else if data := tryDecodeData ( blobData ); data != nil {
251+ displayHeader (result . header )
252+ } else if result . data != nil {
196253 printTypeHeader ("SignedData" , "" )
197- displayData (data )
254+ displayData (result . data )
198255 }
199-
200- fmt .Println ()
201256 }
202257 }
258+ daHeight ++
203259 }
204260
205261 fmt .Println (strings .Repeat ("=" , 50 ))
206262 if foundBlobs == 0 {
207- fmt .Printf ("No blobs found containing height %d in DA range %d-%d\n " , targetHeight , startHeight , startHeight + searchRange - 1 )
263+ if searchRange > 0 {
264+ fmt .Printf ("No blobs found containing height %d in DA range %d-%d\n " , targetHeight , startHeight , startHeight + searchRange - 1 )
265+ } else {
266+ fmt .Printf ("No blobs found containing height %d from DA height %d onwards\n " , targetHeight , startHeight )
267+ }
208268 } else {
209269 fmt .Printf ("Found %d blob(s) containing height %d\n " , foundBlobs , targetHeight )
210270 }
@@ -320,7 +380,11 @@ func printQueryInfo(height uint64, namespace []byte) {
320380
321381func printSearchInfo (startHeight uint64 , namespace []byte , targetHeight , searchRange uint64 ) {
322382 fmt .Printf ("Start DA Height: %d | Namespace: %s | URL: %s" , startHeight , formatHash (hex .EncodeToString (namespace )), daURL )
323- fmt .Printf (" | Target Height: %d | Range: %d" , targetHeight , searchRange )
383+ if searchRange > 0 {
384+ fmt .Printf (" | Target Height: %d | Range: %d" , targetHeight , searchRange )
385+ } else {
386+ fmt .Printf (" | Target Height: %d | Range: unlimited" , targetHeight )
387+ }
324388 fmt .Println ()
325389 fmt .Println ()
326390}
@@ -448,7 +512,7 @@ func printFooter() {
448512 fmt .Printf ("Analysis complete!\n " )
449513}
450514
451- func printError (format string , args ... interface {} ) {
515+ func printError (format string , args ... any ) {
452516 fmt .Fprintf (os .Stderr , "Error: " + format , args ... )
453517}
454518
0 commit comments