Skip to content

Commit 10e4697

Browse files
committed
Handle header and signatures
This change adds real header and signature handling (placeholders are removed). We use Golang's gob to serialize those objects and store them in metadata. Change-Id: If72907341e67cc60ebe74240648e190715dd7b5a Signed-off-by: Gabor Hosszu <[email protected]>
1 parent 0c5736c commit 10e4697

File tree

2 files changed

+120
-6
lines changed

2 files changed

+120
-6
lines changed

orderer/sbft/backend/backend.go

+52-6
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ limitations under the License.
1717
package backend
1818

1919
import (
20+
"bytes"
2021
"fmt"
2122
"io"
2223
"sort"
@@ -37,6 +38,7 @@ import (
3738
"crypto/rsa"
3839
"crypto/sha256"
3940
"encoding/asn1"
41+
"encoding/gob"
4042

4143
"github.com/golang/protobuf/proto"
4244
"github.com/hyperledger/fabric/orderer/rawledger"
@@ -48,6 +50,10 @@ import (
4850
"github.com/op/go-logging"
4951
)
5052

53+
const headerIndex = 0
54+
const signaturesIndex = 1
55+
const metadataLen = 2
56+
5157
var logger = logging.MustGetLogger("backend")
5258

5359
type Backend struct {
@@ -289,9 +295,6 @@ func (t *Backend) Timer(d time.Duration, tf func()) s.Canceller {
289295

290296
// Deliver writes the ledger
291297
func (t *Backend) Deliver(batch *s.Batch) {
292-
// TODO: proof
293-
// TODO: header
294-
// proof := batch.Signatures[0]
295298
blockContents := make([]*cb.Envelope, 0, len(batch.Payloads))
296299
for _, p := range batch.Payloads {
297300
envelope := &cb.Envelope{}
@@ -302,7 +305,12 @@ func (t *Backend) Deliver(batch *s.Batch) {
302305
logger.Warningf("Payload cannot be unmarshalled.")
303306
}
304307
}
305-
t.ledger.Append(blockContents, nil)
308+
// This a quick and dirty solution to make it work.
309+
// SBFT needs to use Rawledger's structures and signatures over the Block.
310+
metadata := make([][]byte, metadataLen)
311+
metadata[headerIndex] = batch.Header
312+
metadata[signaturesIndex] = encodeSignatures(batch.Signatures)
313+
t.ledger.Append(blockContents, metadata)
306314
}
307315

308316
func (t *Backend) Persist(key string, data proto.Message) {
@@ -333,8 +341,8 @@ func (t *Backend) LastBatch() *s.Batch {
333341
if status != cb.Status_SUCCESS {
334342
panic("Fatal ledger error: unable to get last block.")
335343
}
336-
header := []byte{}
337-
sgns := make(map[uint64][]byte)
344+
header := getHeader(block.Metadata)
345+
sgns := decodeSignatures(getEncodedSignatures(block.Metadata))
338346
batch := s.Batch{Header: header, Payloads: data, Signatures: sgns}
339347
return &batch
340348
}
@@ -404,3 +412,41 @@ func CheckSig(publicKey crypto.PublicKey, data []byte, sig []byte) error {
404412
return fmt.Errorf("Unsupported public key type.")
405413
}
406414
}
415+
416+
func getHeader(metadata *cb.BlockMetadata) []byte {
417+
if metadata == nil || len(metadata.Metadata) < metadataLen {
418+
return nil
419+
}
420+
return metadata.Metadata[headerIndex]
421+
}
422+
423+
func getEncodedSignatures(metadata *cb.BlockMetadata) []byte {
424+
if metadata == nil || len(metadata.Metadata) < metadataLen {
425+
return nil
426+
}
427+
return metadata.Metadata[signaturesIndex]
428+
}
429+
430+
func encodeSignatures(signatures map[uint64][]byte) []byte {
431+
var buf bytes.Buffer
432+
enc := gob.NewEncoder(&buf)
433+
err := enc.Encode(signatures)
434+
if err != nil {
435+
panic(err)
436+
}
437+
return buf.Bytes()
438+
}
439+
440+
func decodeSignatures(encodedSignatures []byte) map[uint64][]byte {
441+
if encodedSignatures == nil {
442+
return nil
443+
}
444+
buf := bytes.NewBuffer(encodedSignatures)
445+
var r map[uint64][]byte
446+
dec := gob.NewDecoder(buf)
447+
err := dec.Decode(&r)
448+
if err != nil {
449+
panic(err)
450+
}
451+
return r
452+
}

orderer/sbft/backend/backend_test.go

+68
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,14 @@ import (
2121
"crypto/elliptic"
2222
crand "crypto/rand"
2323
"crypto/rsa"
24+
"reflect"
2425
"testing"
26+
27+
"github.com/golang/protobuf/proto"
28+
"github.com/hyperledger/fabric/orderer/common/bootstrap/static"
29+
"github.com/hyperledger/fabric/orderer/rawledger/ramledger"
30+
"github.com/hyperledger/fabric/orderer/sbft/simplebft"
31+
cb "github.com/hyperledger/fabric/protos/common"
2532
)
2633

2734
func TestSignAndVerifyRsa(t *testing.T) {
@@ -59,3 +66,64 @@ func TestSignAndVerifyEcdsa(t *testing.T) {
5966
t.Errorf("Signature check failed: %s", err)
6067
}
6168
}
69+
70+
func TestLedgerReadWrite(t *testing.T) {
71+
genesis, err := static.New().GenesisBlock()
72+
if err != nil {
73+
panic("Failed to generate genesis block.")
74+
}
75+
_, rl := ramledger.New(10, genesis)
76+
b := Backend{ledger: rl}
77+
78+
header := []byte("header")
79+
e1 := &cb.Envelope{Payload: []byte("data1")}
80+
e2 := &cb.Envelope{Payload: []byte("data2")}
81+
ebytes1, _ := proto.Marshal(e1)
82+
ebytes2, _ := proto.Marshal(e2)
83+
data := [][]byte{ebytes1, ebytes2}
84+
sgns := make(map[uint64][]byte)
85+
sgns[uint64(1)] = []byte("sgn1")
86+
sgns[uint64(22)] = []byte("sgn22")
87+
batch := simplebft.Batch{Header: header, Payloads: data, Signatures: sgns}
88+
89+
b.Deliver(&batch)
90+
batch2 := b.LastBatch()
91+
92+
if !reflect.DeepEqual(batch, *batch2) {
93+
t.Errorf("The wrong batch was returned by LastBatch after Deliver: %v (original was: %v)", batch2, &batch)
94+
}
95+
}
96+
97+
func TestEncoderEncodesDecodesSgnsWithoutPanic(t *testing.T) {
98+
defer func() {
99+
if r := recover(); r != nil {
100+
t.Errorf("Encoding/decoding failed for valid signatures, code panicked.")
101+
}
102+
}()
103+
sgns1 := make(map[uint64][]byte)
104+
e1 := encodeSignatures(sgns1)
105+
106+
sgns2 := make(map[uint64][]byte)
107+
sgns2[uint64(1)] = []byte("sgn1")
108+
e2 := encodeSignatures(sgns2)
109+
110+
sgns3 := make(map[uint64][]byte)
111+
sgns3[uint64(22)] = []byte("sgn22")
112+
sgns3[uint64(143)] = []byte("sgn22")
113+
sgns3[uint64(200)] = []byte("sgn200")
114+
e3 := encodeSignatures(sgns3)
115+
116+
rsgns1 := decodeSignatures(e1)
117+
rsgns2 := decodeSignatures(e2)
118+
rsgns3 := decodeSignatures(e3)
119+
120+
if !reflect.DeepEqual(sgns1, rsgns1) {
121+
t.Errorf("Decoding error: %v (original: %v). (1)", rsgns1, sgns1)
122+
}
123+
if !reflect.DeepEqual(sgns2, rsgns2) {
124+
t.Errorf("Decoding error: %v (original: %v). (2)", rsgns2, sgns2)
125+
}
126+
if !reflect.DeepEqual(sgns3, rsgns3) {
127+
t.Errorf("Decoding error: %v (original: %v). (3)", rsgns3, sgns3)
128+
}
129+
}

0 commit comments

Comments
 (0)