Skip to content

Commit

Permalink
add SMaRtBFT consensus support
Browse files Browse the repository at this point in the history
Signed-off-by: Parameswaran Selvam <parselva@in.ibm.com>
  • Loading branch information
Param-S committed Nov 14, 2022
1 parent 01eeecc commit 6ceb688
Show file tree
Hide file tree
Showing 67 changed files with 13,850 additions and 34 deletions.
106 changes: 106 additions & 0 deletions common/crypto/sanitize.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
/*
Copyright IBM Corp. All Rights Reserved.
SPDX-License-Identifier: Apache-2.0
*/

package crypto

import (
"crypto/ecdsa"
"crypto/x509"
"crypto/x509/pkix"
"encoding/asn1"
"encoding/pem"
"math/big"
"time"

"github.com/golang/protobuf/proto"
"github.com/hyperledger/fabric-protos-go/msp"
"github.com/hyperledger/fabric/bccsp/utils"
"github.com/pkg/errors"
)

// SanitizeIdentity sanitizes the signature scheme of the identity
func SanitizeIdentity(identity []byte) ([]byte, error) {
sID := &msp.SerializedIdentity{}
if err := proto.Unmarshal(identity, sID); err != nil {
return nil, errors.Wrapf(err, "failed unmarshaling identity %s", string(identity))
}

der, _ := pem.Decode(sID.IdBytes)
if der == nil {
return nil, errors.Errorf("failed to PEM decode identity bytes: %s", string(sID.IdBytes))
}
cert, err := x509.ParseCertificate(der.Bytes)
if err != nil {
return nil, errors.Wrapf(err, "failed parsing certificate %s", string(sID.IdBytes))
}

r, s, err := utils.UnmarshalECDSASignature(cert.Signature)
if err != nil {
return nil, errors.Wrapf(err, "failed unmarshaling ECDSA signature on identity: %s", string(sID.IdBytes))
}

// We assume that the consenter and the CA use the same signature scheme.
curveOrderUsedByCryptoGen := cert.PublicKey.(*ecdsa.PublicKey).Curve.Params().N
halfOrder := new(big.Int).Rsh(curveOrderUsedByCryptoGen, 1)
// Low S, nothing to do here!
if s.Cmp(halfOrder) != 1 {
return identity, nil
}
// Else it's high-S, so shift it below half the order.
s.Sub(curveOrderUsedByCryptoGen, s)

var newCert certificate
_, err = asn1.Unmarshal(cert.Raw, &newCert)
if err != nil {
return nil, errors.Wrapf(err, "failed unmarshaling certificate")
}

newSig, err := utils.MarshalECDSASignature(r, s)
if err != nil {
return nil, errors.Wrapf(err, "failed marshaling ECDSA signature")
}
newCert.SignatureValue = asn1.BitString{Bytes: newSig, BitLength: len(newSig) * 8}

newCert.Raw = nil
newRaw, err := asn1.Marshal(newCert)
if err != nil {
return nil, errors.Wrapf(err, "failed marshaling new certificate")
}

sID.IdBytes = pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: newRaw})
return proto.Marshal(sID)
}

type certificate struct {
Raw asn1.RawContent
TBSCertificate tbsCertificate
SignatureAlgorithm pkix.AlgorithmIdentifier
SignatureValue asn1.BitString
}

type tbsCertificate struct {
Raw asn1.RawContent
Version int `asn1:"optional,explicit,default:0,tag:0"`
SerialNumber *big.Int
SignatureAlgorithm pkix.AlgorithmIdentifier
Issuer asn1.RawValue
Validity validity
Subject asn1.RawValue
PublicKey publicKeyInfo
UniqueId asn1.BitString `asn1:"optional,tag:1"`
SubjectUniqueId asn1.BitString `asn1:"optional,tag:2"`
Extensions []pkix.Extension `asn1:"optional,explicit,tag:3"`
}

type validity struct {
NotBefore, NotAfter time.Time
}

type publicKeyInfo struct {
Raw asn1.RawContent
Algorithm pkix.AlgorithmIdentifier
PublicKey asn1.BitString
}
68 changes: 68 additions & 0 deletions common/crypto/signer.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
/*
Copyright IBM Corp. All Rights Reserved.
SPDX-License-Identifier: Apache-2.0
*/

package crypto

import (
cb "github.com/hyperledger/fabric-protos-go/common"
)

// LocalSigner is a temporary stub interface which will be implemented by the local MSP
type LocalSigner interface {
SignatureHeaderMaker
Signer
}

// Signer signs messages
type Signer interface {
// Sign a message and return the signature over the digest, or error on failure
Sign(message []byte) ([]byte, error)
}

// IdentitySerializer serializes identities
type IdentitySerializer interface {
// Serialize converts an identity to bytes
Serialize() ([]byte, error)
}

// SignatureHeaderMaker creates a new SignatureHeader
type SignatureHeaderMaker interface {
// NewSignatureHeader creates a SignatureHeader with the correct signing identity and a valid nonce
NewSignatureHeader() (*cb.SignatureHeader, error)
}

// SignatureHeaderCreator creates signature headers
type SignatureHeaderCreator struct {
SignerSupport
}

// SignerSupport implements the needed support for LocalSigner
type SignerSupport interface {
Signer
IdentitySerializer
}

// NewSignatureHeaderCreator creates new signature headers
func NewSignatureHeaderCreator(ss SignerSupport) *SignatureHeaderCreator {
return &SignatureHeaderCreator{ss}
}

// NewSignatureHeader creates a SignatureHeader with the correct signing identity and a valid nonce
func (bs *SignatureHeaderCreator) NewSignatureHeader() (*cb.SignatureHeader, error) {
creator, err := bs.Serialize()
if err != nil {
return nil, err
}
nonce, err := GetRandomNonce()
if err != nil {
return nil, err
}

return &cb.SignatureHeader{
Creator: creator,
Nonce: nonce,
}, nil
}
20 changes: 20 additions & 0 deletions docs/source/metrics_reference.rst
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,16 @@ The following orderer metrics are exported for consumption by Prometheus.
+----------------------------------------------+-----------+------------------------------------------------------------+-----------+--------------------------------------------------------------------+
| consensus_etcdraft_snapshot_block_number | gauge | The block number of the latest snapshot. | channel | |
+----------------------------------------------+-----------+------------------------------------------------------------+-----------+--------------------------------------------------------------------+
| consensus_smartbft_cluster_size | gauge | Number of nodes in this channel. | channel | |
+----------------------------------------------+-----------+------------------------------------------------------------+-----------+--------------------------------------------------------------------+
| consensus_smartbft_committed_block_number | gauge | The number of the latest committed block. | channel | |
+----------------------------------------------+-----------+------------------------------------------------------------+-----------+--------------------------------------------------------------------+
| consensus_smartbft_is_leader | gauge | The leadership status of the current node according to the | channel | |
| | | latest committed block: 1 if it is the leader else 0. | | |
+----------------------------------------------+-----------+------------------------------------------------------------+-----------+--------------------------------------------------------------------+
| consensus_smartbft_leader_id | gauge | The id of the current leader according to the latest | channel | |
| | | committed block. | | |
+----------------------------------------------+-----------+------------------------------------------------------------+-----------+--------------------------------------------------------------------+
| deliver_blocks_sent | counter | The number of blocks sent by the deliver service. | channel | |
| | | +-----------+--------------------------------------------------------------------+
| | | | filtered | |
Expand Down Expand Up @@ -238,6 +248,16 @@ associated with the metric.
+---------------------------------------------------------------------------+-----------+------------------------------------------------------------+
| consensus.etcdraft.snapshot_block_number.%{channel} | gauge | The block number of the latest snapshot. |
+---------------------------------------------------------------------------+-----------+------------------------------------------------------------+
| consensus.smartbft.cluster_size.%{channel} | gauge | Number of nodes in this channel. |
+---------------------------------------------------------------------------+-----------+------------------------------------------------------------+
| consensus.smartbft.committed_block_number.%{channel} | gauge | The number of the latest committed block. |
+---------------------------------------------------------------------------+-----------+------------------------------------------------------------+
| consensus.smartbft.is_leader.%{channel} | gauge | The leadership status of the current node according to the |
| | | latest committed block: 1 if it is the leader else 0. |
+---------------------------------------------------------------------------+-----------+------------------------------------------------------------+
| consensus.smartbft.leader_id.%{channel} | gauge | The id of the current leader according to the latest |
| | | committed block. |
+---------------------------------------------------------------------------+-----------+------------------------------------------------------------+
| deliver.blocks_sent.%{channel}.%{filtered}.%{data_type} | counter | The number of blocks sent by the deliver service. |
+---------------------------------------------------------------------------+-----------+------------------------------------------------------------+
| deliver.requests_completed.%{channel}.%{filtered}.%{data_type}.%{success} | counter | The number of deliver requests that have been completed. |
Expand Down
6 changes: 4 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ require (
code.cloudfoundry.org/clock v1.0.0
github.com/IBM/idemix v0.0.0-20220112103229-701e7610d405
github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible
github.com/SmartBFT-Go/consensus v0.3.0
github.com/VictoriaMetrics/fastcache v1.9.0
github.com/bits-and-blooms/bitset v1.2.1
github.com/cheggaaa/pb v1.0.29
Expand All @@ -19,7 +20,7 @@ require (
github.com/hyperledger/fabric-chaincode-go v0.0.0-20220713164125-8f0791c989d7
github.com/hyperledger/fabric-config v0.1.0
github.com/hyperledger/fabric-lib-go v1.0.0
github.com/hyperledger/fabric-protos-go v0.0.0-20220827195505-ce4c067a561d
github.com/hyperledger/fabric-protos-go v0.0.0-20221109160343-add83d6f2564
github.com/kr/pretty v0.3.0
github.com/miekg/pkcs11 v1.1.1
github.com/mitchellh/mapstructure v1.4.3
Expand All @@ -37,7 +38,7 @@ require (
go.etcd.io/etcd/client/pkg/v3 v3.5.1
go.etcd.io/etcd/raft/v3 v3.5.1
go.etcd.io/etcd/server/v3 v3.5.1
go.uber.org/zap v1.17.0
go.uber.org/zap v1.19.0
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2
golang.org/x/tools v0.1.2
google.golang.org/grpc v1.47.0
Expand Down Expand Up @@ -102,6 +103,7 @@ require (
go.uber.org/multierr v1.6.0 // indirect
golang.org/x/mod v0.4.2 // indirect
golang.org/x/net v0.0.0-20220225172249-27dd8689420f // indirect
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c // indirect
golang.org/x/sys v0.0.0-20220204135822-1c1b9b1eba6a // indirect
golang.org/x/text v0.3.7 // indirect
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect
Expand Down
Loading

0 comments on commit 6ceb688

Please sign in to comment.