@@ -5,12 +5,13 @@ import (
55 "bytes"
66 "context"
77 "encoding/hex"
8- "errors"
98 "fmt"
109 "io"
1110 "math/rand"
1211 "time"
1312
13+ "github.com/ethersphere/bee/v2/pkg/crypto"
14+ "github.com/ethersphere/bee/v2/pkg/swarm"
1415 "github.com/ethersphere/beekeeper/pkg/bee"
1516 "github.com/ethersphere/beekeeper/pkg/bee/api"
1617 "github.com/ethersphere/beekeeper/pkg/beekeeper"
@@ -58,23 +59,38 @@ func NewCheck(logger logging.Logger) beekeeper.Action {
5859 }
5960}
6061
61- var errManifest = errors .New ("manifest data mismatch" )
62-
6362func (c * Check ) Run (ctx context.Context , cluster orchestration.Cluster , opts interface {}) (err error ) {
6463 o , ok := opts .(Options )
6564 if ! ok {
6665 return fmt .Errorf ("invalid options type" )
6766 }
6867
6968 rnd := random .PseudoGenerator (o .Seed )
69+ clients , err := cluster .ShuffledFullNodeClients (ctx , rnd )
70+ if err != nil {
71+ return fmt .Errorf ("node clients shuffle: %w" , err )
72+ }
7073
71- c .logger .Infof ("Seed: %d" , o .Seed )
74+ if len (clients ) < 2 {
75+ return fmt .Errorf ("not enough nodes to run manifest check" )
76+ }
77+ upClient := clients [0 ]
78+ downClient := clients [1 ]
7279
73- overlays , err := cluster . FlattenOverlays (ctx )
80+ err = c . checkWithoutSubDirs (ctx , rnd , o , upClient , downClient )
7481 if err != nil {
75- return err
82+ return fmt . Errorf ( "check without subdirs: %w" , err )
7683 }
7784
85+ err = c .checkWithSubDirs (ctx , rnd , o , upClient , downClient )
86+ if err != nil {
87+ return fmt .Errorf ("check with subdirs: %w" , err )
88+ }
89+
90+ return nil
91+ }
92+
93+ func (c * Check ) checkWithoutSubDirs (ctx context.Context , rnd * rand.Rand , o Options , upClient * bee.Client , downClient * bee.Client ) error {
7894 files , err := generateFiles (rnd , o .FilesInCollection , o .MaxPathnameLength )
7995 if err != nil {
8096 return err
@@ -86,55 +102,167 @@ func (c *Check) Run(ctx context.Context, cluster orchestration.Cluster, opts int
86102 }
87103
88104 tarFile := bee .NewBufferFile ("" , tarReader )
89- clients , err := cluster .NodesClients (ctx )
105+ batchID , err := upClient .GetOrCreateMutableBatch (ctx , o .PostageAmount , o .PostageDepth , o .PostageLabel )
106+ if err != nil {
107+ return fmt .Errorf ("node %s: batch id %w" , upClient .Name (), err )
108+ }
109+ c .logger .Infof ("node %s: batch id %s" , upClient .Name (), batchID )
110+
111+ if err := upClient .UploadCollection (ctx , & tarFile , api.UploadOptions {BatchID : batchID }); err != nil {
112+ return fmt .Errorf ("node %d: %w" , 0 , err )
113+ }
114+
115+ for _ , file := range files {
116+ if err := c .downloadAndVerify (ctx , downClient , tarFile .Address (), & file , bee.File {}); err != nil {
117+ return err
118+ }
119+ }
120+ return nil
121+ }
122+
123+ func (c * Check ) checkWithSubDirs (ctx context.Context , rnd * rand.Rand , o Options , upClient * bee.Client , downClient * bee.Client ) error {
124+ privKey , err := crypto .GenerateSecp256k1Key ()
90125 if err != nil {
91126 return err
92127 }
93128
94- sortedNodes := cluster .FullNodeNames ()
95- node := sortedNodes [0 ]
129+ signer := crypto .NewDefaultSigner (privKey )
130+ topic , err := crypto .LegacyKeccak256 ([]byte ("my-website" ))
131+ if err != nil {
132+ return err
133+ }
96134
97- client := clients [node ]
135+ batchID , err := upClient .GetOrCreateMutableBatch (ctx , o .PostageAmount , o .PostageDepth , o .PostageLabel )
136+ if err != nil {
137+ return fmt .Errorf ("node %s: batch id %w" , upClient .Name (), err )
138+ }
139+ c .logger .Infof ("node %s: batch id %s" , upClient .Name (), batchID )
98140
99- batchID , err := client . GetOrCreateMutableBatch (ctx , o . PostageAmount , o . PostageDepth , o . PostageLabel )
141+ rootFeedRef , err := upClient . CreateRootFeedManifest (ctx , signer , topic , api. UploadOptions { BatchID : batchID } )
100142 if err != nil {
101- return fmt . Errorf ( "node %s: batch id %w" , node , err )
143+ return err
102144 }
103- c .logger .Infof ("node %s: batch id %s" , node , batchID )
145+ c .logger .Infof ("root feed reference: %s" , rootFeedRef .Reference )
146+ time .Sleep (3 * time .Second )
104147
105- if err := client .UploadCollection (ctx , & tarFile , api.UploadOptions {BatchID : batchID }); err != nil {
106- return fmt .Errorf ("node %d: %w" , 0 , err )
148+ paths := []string {"index.html" , "assets/styles/styles.css" , "assets/styles/images/image.png" , "error.html" }
149+ files , err := generateFilesWithPaths (rnd , paths , int (o .MaxPathnameLength ))
150+ if err != nil {
151+ return err
107152 }
108153
109- lastNode := sortedNodes [len (sortedNodes )- 1 ]
110- try := 0
154+ tarReader , err := tarFiles (files )
155+ if err != nil {
156+ return err
157+ }
158+ tarFile := bee .NewBufferFile ("" , tarReader )
159+ if err := upClient .UploadCollection (ctx , & tarFile , api.UploadOptions {BatchID : batchID , IndexDocument : "index.html" }); err != nil {
160+ return err
161+ }
162+ c .logger .Infof ("collection uploaded: %s" , tarFile .Address ())
163+ time .Sleep (3 * time .Second )
111164
112- DOWNLOAD:
113- time .Sleep (5 * time .Second )
114- try ++
115- if try > 5 {
116- return errors .New ("failed getting manifest files after too many retries" )
165+ // push first version of website to the feed
166+ ref , err := upClient .UpdateFeedWithReference (ctx , signer , topic , 0 , tarFile .Address (), api.UploadOptions {BatchID : batchID })
167+ if err != nil {
168+ return err
169+ }
170+ c .logger .Infof ("feed updated: %s" , ref .Reference )
171+
172+ // download root (index.html) from the feed
173+ err = c .downloadAndVerify (ctx , downClient , rootFeedRef .Reference , nil , files [0 ])
174+ if err != nil {
175+ return err
176+ }
177+
178+ // update website files
179+ files , err = generateFilesWithPaths (rnd , paths , int (o .MaxPathnameLength ))
180+ if err != nil {
181+ return err
182+ }
183+
184+ tarReader , err = tarFiles (files )
185+ if err != nil {
186+ return err
187+ }
188+ tarFile = bee .NewBufferFile ("" , tarReader )
189+ if err := upClient .UploadCollection (ctx , & tarFile , api.UploadOptions {BatchID : batchID , IndexDocument : "index.html" }); err != nil {
190+ return err
117191 }
192+ c .logger .Infof ("collection uploaded: %s" , tarFile .Address ())
193+ time .Sleep (3 * time .Second )
118194
119- for i , file := range files {
120- node := clients [lastNode ]
195+ // push 2nd version of website to the feed
196+ ref , err = upClient .UpdateFeedWithReference (ctx , signer , topic , 1 , tarFile .Address (), api.UploadOptions {BatchID : batchID })
197+ if err != nil {
198+ return err
199+ }
200+ c .logger .Infof ("feed updated: %s" , ref .Reference )
121201
122- size , hash , err := node .DownloadManifestFile (ctx , tarFile .Address (), file .Name ())
202+ // download updated index.html from the feed
203+ err = c .downloadAndVerify (ctx , downClient , rootFeedRef .Reference , nil , files [0 ])
204+ if err != nil {
205+ return err
206+ }
207+
208+ // download other paths and compare
209+ for i := 0 ; i < len (files ); i ++ {
210+ err = c .downloadAndVerify (ctx , downClient , tarFile .Address (), & files [i ], files [0 ])
123211 if err != nil {
124- c .logger .Infof ("Node %s. Error retrieving file: %v" , lastNode , err )
125- goto DOWNLOAD
212+ return err
126213 }
214+ }
215+ return nil
216+ }
127217
128- if ! bytes .Equal (file .Hash (), hash ) {
129- c .logger .Infof ("Node %s. File %d not retrieved successfully. Uploaded size: %d Downloaded size: %d Node: %s File: %s/%s" , lastNode , i , file .Size (), size , overlays [lastNode ].String (), tarFile .Address ().String (), file .Name ())
130- return errManifest
218+ // downloadAndVerify retrieves a file from the given address using the specified client.
219+ // If the file parameter is nil, it downloads the index file in the collection.
220+ // Then it verifies the hash of the downloaded file against the expected hash.
221+ func (c * Check ) downloadAndVerify (ctx context.Context , client * bee.Client , address swarm.Address , file * bee.File , indexFile bee.File ) error {
222+ expectedHash := indexFile .Hash ()
223+ fName := ""
224+ if file != nil {
225+ fName = file .Name ()
226+ expectedHash = file .Hash ()
227+ }
228+ c .logger .Infof ("downloading file: %s/%s" , address , fName )
229+
230+ for i := 0 ; i < 10 ; i ++ {
231+ select {
232+ case <- time .After (5 * time .Second ):
233+ _ , hash , err := client .DownloadManifestFile (ctx , address , fName )
234+ if err != nil {
235+ c .logger .Infof ("node %s: error retrieving file: %s" , client .Name (), err .Error ())
236+ continue
237+ }
238+
239+ c .logger .Infof ("want hash: %s, got hash: %s" , hex .EncodeToString (expectedHash ), hex .EncodeToString (hash ))
240+ if ! bytes .Equal (expectedHash , hash ) {
241+ c .logger .Infof ("node %s: file hash does not match." , client .Name ())
242+ continue
243+ }
244+ c .logger .Infof ("node %s: file retrieved successfully" , client .Name ())
245+ return nil
246+ case <- ctx .Done ():
247+ return ctx .Err ()
131248 }
132-
133- c .logger .Infof ("Node %s. File %d retrieved successfully. Node: %s File: %s/%s" , lastNode , i , overlays [lastNode ].String (), tarFile .Address ().String (), file .Name ())
134- try = 0 // reset the retry counter for the next file
135249 }
136250
137- return nil
251+ return fmt .Errorf ("failed getting manifest file after too many retries" )
252+ }
253+
254+ func generateFilesWithPaths (r * rand.Rand , paths []string , maxSize int ) ([]bee.File , error ) {
255+ files := make ([]bee.File , len (paths ))
256+ for i , path := range paths {
257+ size := int64 (r .Intn (maxSize )) + 1
258+ file := bee .NewRandomFile (r , path , size )
259+ err := file .CalculateHash ()
260+ if err != nil {
261+ return nil , err
262+ }
263+ files [i ] = file
264+ }
265+ return files , nil
138266}
139267
140268func generateFiles (r * rand.Rand , filesCount int , maxPathnameLength int32 ) ([]bee.File , error ) {
@@ -171,6 +299,8 @@ func tarFiles(files []bee.File) (*bytes.Buffer, error) {
171299 var buf bytes.Buffer
172300 tw := tar .NewWriter (& buf )
173301
302+ defer tw .Close ()
303+
174304 for _ , file := range files {
175305 // create tar header and write it
176306 hdr := & tar.Header {
@@ -193,9 +323,5 @@ func tarFiles(files []bee.File) (*bytes.Buffer, error) {
193323 }
194324 }
195325
196- if err := tw .Close (); err != nil {
197- return nil , err
198- }
199-
200326 return & buf , nil
201327}
0 commit comments