github.com/lazyledger/lazyledger-core@v0.35.0-dev.0.20210613111200-4c651f053571/p2p/ipld/validate.go (about) 1 package ipld 2 3 import ( 4 "context" 5 "errors" 6 "fmt" 7 "time" 8 9 ipld "github.com/ipfs/go-ipld-format" 10 "github.com/lazyledger/nmt/namespace" 11 12 "github.com/lazyledger/lazyledger-core/types" 13 ) 14 15 // ValidationTimeout specifies timeout for DA validation during which data have to be found on the network, 16 // otherwise ErrValidationFailed is thrown. 17 // TODO: github.com/lazyledger/lazyledger-core/issues/280 18 const ValidationTimeout = 10 * time.Minute 19 20 // ErrValidationFailed is returned whenever DA validation fails 21 var ErrValidationFailed = errors.New("validation failed") 22 23 // ValidateAvailability randomly samples the block data that composes a provided 24 // data availability header. It only returns when all samples have been completed 25 // successfully. `onLeafValidity` is called on each sampled leaf after 26 // retrieval. Implements the protocol described in 27 // https://fc21.ifca.ai/papers/83.pdf. 28 func ValidateAvailability( 29 ctx context.Context, 30 dag ipld.NodeGetter, 31 dah *types.DataAvailabilityHeader, 32 numSamples int, 33 onLeafValidity func(namespace.PrefixedData8), 34 ) error { 35 ctx, cancel := context.WithTimeout(ctx, ValidationTimeout) 36 defer cancel() 37 38 squareWidth := uint32(len(dah.ColumnRoots)) 39 samples := SampleSquare(squareWidth, numSamples) 40 41 type res struct { 42 data []byte 43 err error 44 } 45 resCh := make(chan res, len(samples)) 46 for _, s := range samples { 47 go func(s Sample) { 48 root, leaf, err := s.Leaf(dah) 49 if err != nil { 50 select { 51 case resCh <- res{err: err}: 52 case <-ctx.Done(): 53 } 54 return 55 } 56 57 data, err := GetLeafData(ctx, root, leaf, squareWidth, dag) 58 select { 59 case resCh <- res{data: data, err: err}: 60 case <-ctx.Done(): 61 } 62 }(s) 63 } 64 65 for range samples { 66 select { 67 case r := <-resCh: 68 if r.err != nil { 69 if errors.Is(r.err, ipld.ErrNotFound) { 70 return ErrValidationFailed 71 } 72 73 return r.err 74 } 75 76 // the fact that we read the data, already gives us Merkle proof, 77 // thus the data availability is successfully validated :) 78 onLeafValidity(r.data) 79 case <-ctx.Done(): 80 err := ctx.Err() 81 if err == context.DeadlineExceeded { 82 return fmt.Errorf("%v: %w", ErrValidationFailed, err) 83 } 84 85 return err 86 } 87 } 88 89 return nil 90 }