github.com/celestiaorg/celestia-node@v0.15.0-beta.1/share/eds/retriever_quadrant.go (about) 1 package eds 2 3 import ( 4 "math/rand" 5 "time" 6 7 "github.com/ipfs/go-cid" 8 9 "github.com/celestiaorg/celestia-app/pkg/da" 10 "github.com/celestiaorg/rsmt2d" 11 12 "github.com/celestiaorg/celestia-node/share/ipld" 13 ) 14 15 const ( 16 // there are always 4 quadrants 17 numQuadrants = 4 18 // blockTime equals to the time with which new blocks are produced in the network. 19 // TODO(@Wondertan): Here we assume that the block time is a minute, but 20 // block time is a network wide variable/param that has to be taken from 21 // a proper place 22 blockTime = time.Minute 23 ) 24 25 // RetrieveQuadrantTimeout defines how much time Retriever waits before 26 // starting to retrieve another quadrant. 27 // 28 // NOTE: 29 // - The whole data square must be retrieved in less than block time. 30 // - We have 4 quadrants from two sources(rows, cols) which equals to 8 in total. 31 var RetrieveQuadrantTimeout = blockTime / numQuadrants * 2 32 33 type quadrant struct { 34 // slice of roots to get shares from 35 roots []cid.Cid 36 // Example coordinates(x;y) of each quadrant when fetching from column roots 37 // ------ ------- 38 // | Q0 | | Q1 | 39 // |(0;0)| |(1;0)| 40 // ------ ------- 41 // | Q2 | | Q3 | 42 // |(0;1)| |(1;1)| 43 // ------ ------- 44 x, y int 45 // source defines the axis(Row or Col) to fetch the quadrant from 46 source rsmt2d.Axis 47 } 48 49 // newQuadrants constructs a slice of quadrants from DAHeader. 50 // There are always 4 quadrants per each source (row and col), so 8 in total. 51 // The ordering of quadrants is random. 52 func newQuadrants(dah *da.DataAvailabilityHeader) []*quadrant { 53 // combine all the roots into one slice, so they can be easily accessible by index 54 daRoots := [][][]byte{ 55 dah.RowRoots, 56 dah.ColumnRoots, 57 } 58 // create a quadrant slice for each source(row;col) 59 sources := [][]*quadrant{ 60 make([]*quadrant, numQuadrants), 61 make([]*quadrant, numQuadrants), 62 } 63 for source, quadrants := range sources { 64 size, qsize := len(daRoots[source]), len(daRoots[source])/2 65 roots := make([]cid.Cid, size) 66 for i, root := range daRoots[source] { 67 roots[i] = ipld.MustCidFromNamespacedSha256(root) 68 } 69 70 for i := range quadrants { 71 // convert quadrant 1D into into 2D coordinates 72 x, y := i%2, i/2 73 quadrants[i] = &quadrant{ 74 roots: roots[qsize*y : qsize*(y+1)], 75 x: x, 76 y: y, 77 source: rsmt2d.Axis(source), 78 } 79 } 80 } 81 quadrants := make([]*quadrant, 0, numQuadrants*2) 82 for _, qs := range sources { 83 quadrants = append(quadrants, qs...) 84 } 85 // shuffle quadrants to be fetched in random order 86 rand.Shuffle(len(quadrants), func(i, j int) { quadrants[i], quadrants[j] = quadrants[j], quadrants[i] }) 87 return quadrants 88 } 89 90 // pos calculates position of a share in a data square. 91 func (q *quadrant) pos(rootIdx, cellIdx int) (int, int) { 92 cellIdx += len(q.roots) * q.x 93 rootIdx += len(q.roots) * q.y 94 switch q.source { 95 case rsmt2d.Row: 96 return rootIdx, cellIdx 97 case rsmt2d.Col: 98 return cellIdx, rootIdx 99 default: 100 panic("unknown axis") 101 } 102 }