@@ -17,7 +17,9 @@ limitations under the License.
17
17
package ordererledger
18
18
19
19
import (
20
+ "github.com/golang/protobuf/proto"
20
21
cb "github.com/hyperledger/fabric/protos/common"
22
+ ab "github.com/hyperledger/fabric/protos/orderer"
21
23
)
22
24
23
25
var closedChan chan struct {}
@@ -27,7 +29,8 @@ func init() {
27
29
close (closedChan )
28
30
}
29
31
30
- // NotFoundErrorIterator simply always returns an error of cb.Status_NOT_FOUND, and is generally useful for implementations of the Reader interface
32
+ // NotFoundErrorIterator simply always returns an error of cb.Status_NOT_FOUND,
33
+ // and is generally useful for implementations of the Reader interface
31
34
type NotFoundErrorIterator struct {}
32
35
33
36
// Next returns nil, cb.Status_NOT_FOUND
@@ -39,3 +42,64 @@ func (nfei *NotFoundErrorIterator) Next() (*cb.Block, cb.Status) {
39
42
func (nfei * NotFoundErrorIterator ) ReadyChan () <- chan struct {} {
40
43
return closedChan
41
44
}
45
+
46
+ // CreateNextBlock provides a utility way to construct the next block from
47
+ // contents and metadata for a given ledger
48
+ // XXX This will need to be modified to accept marshaled envelopes
49
+ // to accomodate non-deterministic marshaling
50
+ func CreateNextBlock (rl Reader , messages []* cb.Envelope ) * cb.Block {
51
+ var nextBlockNumber uint64
52
+ var previousBlockHash []byte
53
+
54
+ if rl .Height () > 0 {
55
+ it , _ := rl .Iterator (& ab.SeekPosition {
56
+ Type : & ab.SeekPosition_Newest {
57
+ & ab.SeekNewest {},
58
+ },
59
+ })
60
+ <- it .ReadyChan () // Should never block, but just in case
61
+ block , status := it .Next ()
62
+ if status != cb .Status_SUCCESS {
63
+ panic ("Error seeking to newest block for chain with non-zero height" )
64
+ }
65
+ nextBlockNumber = block .Header .Number + 1
66
+ previousBlockHash = block .Header .Hash ()
67
+ }
68
+
69
+ data := & cb.BlockData {
70
+ Data : make ([][]byte , len (messages )),
71
+ }
72
+
73
+ var err error
74
+ for i , msg := range messages {
75
+ data .Data [i ], err = proto .Marshal (msg )
76
+ if err != nil {
77
+ panic (err )
78
+ }
79
+ }
80
+
81
+ block := cb .NewBlock (nextBlockNumber , previousBlockHash )
82
+ block .Header .DataHash = data .Hash ()
83
+ block .Data = data
84
+
85
+ return block
86
+ }
87
+
88
+ // GetBlock is a utility method for retrieving a single block
89
+ func GetBlock (rl Reader , index uint64 ) * cb.Block {
90
+ i , _ := rl .Iterator (& ab.SeekPosition {
91
+ Type : & ab.SeekPosition_Specified {
92
+ Specified : & ab.SeekSpecified {Number : index },
93
+ },
94
+ })
95
+ select {
96
+ case <- i .ReadyChan ():
97
+ block , status := i .Next ()
98
+ if status != cb .Status_SUCCESS {
99
+ return nil
100
+ }
101
+ return block
102
+ default :
103
+ return nil
104
+ }
105
+ }
0 commit comments