Skip to content

Commit 7a06098

Browse files
committed
Enable multiple policies type
This commit updates the proto messages to define policy using various rules such as threshold, signature, and hierarchical. Signed-off-by: senthil <[email protected]>
1 parent da4efa0 commit 7a06098

35 files changed

+1100
-311
lines changed

api/protoblocktx/block_tx.pb.go

Lines changed: 513 additions & 166 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

api/protoblocktx/block_tx.proto

Lines changed: 56 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,14 @@ option go_package = "github.com/hyperledger/fabric-x-committer/api/protoblocktx"
1010

1111
package protoblocktx;
1212

13-
// Represents a transaction in the blockchain.
1413
message Tx {
15-
repeated TxNamespace namespaces = 1; // Namespaces associated with the transaction.
16-
repeated bytes signatures = 2; // Signature per namespace.
14+
// A list of namespaces that define the transaction's scope.
15+
repeated TxNamespace namespaces = 1;
16+
17+
// A list of signature sets.
18+
// IMPORTANT: This list MUST be the same size as the namespaces list.
19+
// The SignatureSet at index i corresponds to the namespace at index i.
20+
repeated SignatureSet signature_sets = 2;
1721
}
1822

1923
// Represents a namespace within a transaction.
@@ -44,10 +48,56 @@ message Write {
4448
bytes value = 2; // The value associated with the key being written.
4549
}
4650

51+
// SignatureSet holds all the signatures that correspond to a single namespace
52+
// in the transaction's namespaces list.
53+
message SignatureSet {
54+
// The list of individual signatures for the corresponding namespace.
55+
repeated SignatureWithIdentity signatures_with_identity = 1;
56+
}
57+
58+
// SignatureWithIdentity bundles a single signature with the identity of its creator.
59+
message SignatureWithIdentity {
60+
// The actual cryptographic signature bytes.
61+
bytes signature = 1;
62+
63+
// The identity of the creator who produced the signature.
64+
Identity identity = 2;
65+
}
66+
67+
message Identity {
68+
// The identifier of the associated membership service provider
69+
string msp_id = 1;
70+
71+
oneof creator {
72+
// The full raw bytes of the creator's certificate (e.g., an X.509 certificate).
73+
bytes certificate= 2;
74+
75+
// An identifier for a certificate that is pre-stored or known by the committer.
76+
string certificate_id = 3;
77+
}
78+
}
79+
4780
// Represents a namespace policy.
4881
message NamespacePolicy {
49-
string scheme = 1; // The scheme for signature verification.
50-
bytes public_key = 2; // The public key for signature verification.
82+
string scheme = 1; // The scheme for signature verification.
83+
bytes policy = 2; // The policy rule.
84+
PolicyType type = 3; // The type of policy used.
85+
}
86+
87+
enum PolicyType {
88+
// A policy for verifying a single signature that was generated via a Threshold Signature
89+
// Scheme (TSS). In a TSS, a threshold (T) of N parties must cooperate to
90+
// collectively compute and produce the single signature.
91+
THRESHOLD_RULE = 0;
92+
93+
// A policy defined by an explicit rule that evaluates one or more required signatures.
94+
// For example: "OR('Org1MSP.admin', 'Org2MSP.admin')"
95+
SIGNATURE_RULE = 1;
96+
97+
// A policy that implicitly aggregates the results of policies defined at a lower
98+
// level in the configuration hierarchy. For example, a MAJORITY rule on the
99+
// Admins policies of all member organizations.
100+
HIERARCHICAL_RULE = 2;
51101
}
52102

53103
message BlockInfo {
@@ -78,7 +128,7 @@ message NamespacePolicies {
78128

79129
message PolicyItem {
80130
string namespace = 1;
81-
bytes policy = 2;
131+
bytes policy = 2; // This holds the complete NamespacePolicy.
82132
uint64 version = 3;
83133
}
84134

go.mod

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ go 1.24.3
88

99
require (
1010
github.com/cenkalti/backoff/v4 v4.3.0
11-
github.com/cockroachdb/errors v1.11.3
11+
github.com/cockroachdb/errors v1.12.0
1212
github.com/consensys/gnark-crypto v0.14.0
1313
github.com/docker/docker v28.0.0+incompatible
1414
github.com/docker/go-connections v0.5.0
@@ -20,7 +20,7 @@ require (
2020
github.com/hyperledger/fabric v1.4.0-rc1.0.20240918034325-94590aa4332b
2121
github.com/hyperledger/fabric-lib-go v1.1.3-0.20240523144151-25edd1eaf5f5
2222
github.com/hyperledger/fabric-protos-go-apiv2 v0.3.3
23-
github.com/hyperledger/fabric-x-common v0.0.0-20250701155113-a1ddf93333d8
23+
github.com/hyperledger/fabric-x-common v0.0.0-20250916061807-0d5dacc2a10f
2424
github.com/jackc/puddle v1.3.0
2525
github.com/mitchellh/mapstructure v1.5.0
2626
github.com/onsi/gomega v1.34.2
@@ -79,6 +79,7 @@ require (
7979
github.com/gogo/protobuf v1.3.2 // indirect
8080
github.com/golang/snappy v0.0.4 // indirect
8181
github.com/google/go-cmp v0.6.0 // indirect
82+
github.com/google/pprof v0.0.0-20240827171923-fa2c70bbbfe5 // indirect
8283
github.com/hyperledger-labs/SmartBFT v0.0.0-20240916013553-852e5be5889b // indirect
8384
github.com/hyperledger/aries-bbs-go v0.0.0-20240528084656-761671ea73bc // indirect
8485
github.com/hyperledger/fabric-amcl v0.0.0-20230602173724-9e02669dceb2 // indirect
@@ -113,6 +114,7 @@ require (
113114
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
114115
github.com/nxadm/tail v1.4.11 // indirect
115116
github.com/onsi/ginkgo v1.16.5 // indirect
117+
github.com/onsi/ginkgo/v2 v2.20.2 // indirect
116118
github.com/opencontainers/go-digest v1.0.0 // indirect
117119
github.com/opencontainers/image-spec v1.1.0 // indirect
118120
github.com/pelletier/go-toml/v2 v2.2.3 // indirect

go.sum

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -673,8 +673,8 @@ github.com/cncf/xds/go v0.0.0-20230105202645-06c439db220b/go.mod h1:eXthEFrGJvWH
673673
github.com/cncf/xds/go v0.0.0-20230310173818-32f1caf87195/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
674674
github.com/cockroachdb/apd v1.1.0 h1:3LFP3629v+1aKXU5Q37mxmRxX/pIu1nijXydLShEq5I=
675675
github.com/cockroachdb/apd v1.1.0/go.mod h1:8Sl8LxpKi29FqWXR16WEFZRNSz3SoPzUzeMeY4+DwBQ=
676-
github.com/cockroachdb/errors v1.11.3 h1:5bA+k2Y6r+oz/6Z/RFlNeVCesGARKuC6YymtcDrbC/I=
677-
github.com/cockroachdb/errors v1.11.3/go.mod h1:m4UIW4CDjx+R5cybPsNrRbreomiFqt8o1h1wUVazSd8=
676+
github.com/cockroachdb/errors v1.12.0 h1:d7oCs6vuIMUQRVbi6jWWWEJZahLCfJpnJSVobd1/sUo=
677+
github.com/cockroachdb/errors v1.12.0/go.mod h1:SvzfYNNBshAVbZ8wzNc/UPK3w1vf0dKDUP41ucAIf7g=
678678
github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b h1:r6VH0faHjZeQy818SGhaone5OnYfxFR/+AzdY3sf5aE=
679679
github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b/go.mod h1:Vz9DsVWQQhf3vs21MhPMZpMGSht7O/2vFW2xusFUVOs=
680680
github.com/cockroachdb/redact v1.1.5 h1:u1PMllDkdFfPWaNGMyLD1+so+aq3uUItthCFqzwPJ30=
@@ -921,8 +921,10 @@ github.com/hyperledger/fabric-lib-go v1.1.3-0.20240523144151-25edd1eaf5f5 h1:RPW
921921
github.com/hyperledger/fabric-lib-go v1.1.3-0.20240523144151-25edd1eaf5f5/go.mod h1:SHNCq8AB0VpHAmvJEtdbzabv6NNV1F48JdmDihasBjc=
922922
github.com/hyperledger/fabric-protos-go-apiv2 v0.3.3 h1:Xpd6fzG/KjAOHJsq7EQXY2l+qi/y8muxBaY7R6QWABk=
923923
github.com/hyperledger/fabric-protos-go-apiv2 v0.3.3/go.mod h1:2pq0ui6ZWA0cC8J+eCErgnMDCS1kPOEYVY+06ZAK0qE=
924-
github.com/hyperledger/fabric-x-common v0.0.0-20250701155113-a1ddf93333d8 h1:6cGlSZDuTxCIFOU2JUNDoaFoxZRhchJ3oncTGo9GDOE=
925-
github.com/hyperledger/fabric-x-common v0.0.0-20250701155113-a1ddf93333d8/go.mod h1:xO5q1ytO5d5/DeWkDKMGAgoaWBnhmLIjT/ZS2BZfFVs=
924+
github.com/hyperledger/fabric-x-common v0.0.0-20250907124409-88f08cdf7476 h1:+tTSBVeQUr1a9bNiN7ySvsfDySGAHWvBzlYtLRlowvo=
925+
github.com/hyperledger/fabric-x-common v0.0.0-20250907124409-88f08cdf7476/go.mod h1:rZykFq62cc4k4cDuUytAWd6T1Cfun4Wy5roMNCA85GQ=
926+
github.com/hyperledger/fabric-x-common v0.0.0-20250916061807-0d5dacc2a10f h1:X2JNwMg6cYDCFcxfS47+Fskst2aI3GfllNLNHNOC8qY=
927+
github.com/hyperledger/fabric-x-common v0.0.0-20250916061807-0d5dacc2a10f/go.mod h1:rZykFq62cc4k4cDuUytAWd6T1Cfun4Wy5roMNCA85GQ=
926928
github.com/iancoleman/strcase v0.2.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho=
927929
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
928930
github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=

integration/runner/runtime.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -387,9 +387,9 @@ func (c *CommitterRuntime) MakeAndSendTransactionsToOrderer(
387387
Namespaces: namespaces,
388388
}
389389
if expectedStatus != nil && expectedStatus[i] == protoblocktx.Status_ABORTED_SIGNATURE_INVALID {
390-
tx.Signatures = make([][]byte, len(namespaces))
390+
tx.SignatureSets = make([]*protoblocktx.SignatureSet, len(namespaces))
391391
for nsIdx := range namespaces {
392-
tx.Signatures[nsIdx] = []byte("dummy")
392+
tx.SignatureSets[nsIdx] = test.CreateSignatureSetsForThresholdRule([]byte("dummy"))[0]
393393
}
394394
}
395395
txs[i] = c.TxBuilder.MakeTx(tx)

integration/test/config_update_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ func TestConfigUpdate(t *testing.T) {
9191
ordererEnv.SubmitConfigBlock(t, &workload.ConfigBlock{
9292
ChannelID: c.SystemConfig.Policy.ChannelID,
9393
OrdererEndpoints: endpoints,
94-
MetaNamespaceVerificationKey: metaPolicy.PublicKey,
94+
MetaNamespaceVerificationKey: metaPolicy.Policy,
9595
})
9696
}
9797
submitConfigBlock(ordererEnv.AllRealOrdererEndpoints())

loadgen/workload/config_tx.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ func CreateConfigBlock(policy *PolicyProfile) (*common.Block, error) {
9797

9898
// CreateDefaultConfigBlock creates a config block with default values.
9999
func CreateDefaultConfigBlock(conf *ConfigBlock) (*common.Block, error) {
100-
configBlock := genesisconfig.Load(genesisconfig.SampleFabricX, configtest.GetDevConfigDir())
100+
configBlock := genesisconfig.Load(genesisconfig.TwoOrgsSampleFabricX, configtest.GetDevConfigDir())
101101
tlsCertPath := filepath.Join(configtest.GetDevConfigDir(), "msp", "tlscacerts", "tlsroot.pem")
102102
for _, consenter := range configBlock.Orderer.ConsenterMapping {
103103
consenter.Identity = tlsCertPath

loadgen/workload/conflicts.go

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import (
1111
"math/rand"
1212

1313
"github.com/hyperledger/fabric-x-committer/api/protoblocktx"
14+
"github.com/hyperledger/fabric-x-committer/utils/test"
1415
)
1516

1617
// Dependency types.
@@ -61,9 +62,9 @@ func newSignTxModifier(rnd *rand.Rand, profile *Profile) *signTxModifier {
6162
func (g *signTxModifier) Modify(tx *protoblocktx.Tx) {
6263
if g.invalidSignGenerator.Next() {
6364
// Pre-assigning prevents TxBuilder from re-signing the TX.
64-
tx.Signatures = make([][]byte, len(tx.Namespaces))
65-
for i := range tx.Namespaces {
66-
tx.Signatures[i] = g.invalidSignature
65+
tx.SignatureSets = make([]*protoblocktx.SignatureSet, len(tx.Namespaces))
66+
for i := range len(tx.Namespaces) {
67+
tx.SignatureSets[i] = test.CreateSignatureSetsForThresholdRule(g.invalidSignature)[0]
6768
}
6869
}
6970
}

loadgen/workload/sign.go

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import (
1717
"github.com/hyperledger/fabric-x-committer/utils/logging"
1818
"github.com/hyperledger/fabric-x-committer/utils/signature"
1919
"github.com/hyperledger/fabric-x-committer/utils/signature/sigtest"
20+
"github.com/hyperledger/fabric-x-committer/utils/test"
2021
)
2122

2223
var logger = logging.New("load-gen-sign")
@@ -57,19 +58,19 @@ func NewTxSignerVerifier(policy *PolicyProfile) *TxSignerVerifier {
5758

5859
// Sign signs a TX.
5960
func (e *TxSignerVerifier) Sign(txID string, tx *protoblocktx.Tx) {
60-
tx.Signatures = make([][]byte, len(tx.Namespaces))
61+
tx.SignatureSets = make([]*protoblocktx.SignatureSet, len(tx.Namespaces))
6162
for nsIndex, ns := range tx.Namespaces {
6263
signer, ok := e.HashSigners[ns.NsId]
6364
if !ok {
6465
continue
6566
}
66-
tx.Signatures[nsIndex] = signer.Sign(txID, tx, nsIndex)
67+
tx.SignatureSets[nsIndex] = test.CreateSignatureSetsForThresholdRule(signer.Sign(txID, tx, nsIndex))[0]
6768
}
6869
}
6970

7071
// Verify verifies a signature on the transaction.
7172
func (e *TxSignerVerifier) Verify(txID string, tx *protoblocktx.Tx) bool {
72-
if len(tx.Signatures) < len(tx.Namespaces) {
73+
if len(tx.SignatureSets) < len(tx.Namespaces) {
7374
return false
7475
}
7576

@@ -130,8 +131,8 @@ func (e *HashSignerVerifier) Verify(txID string, tx *protoblocktx.Tx, nsIndex in
130131
// GetVerificationPolicy returns the verification policy.
131132
func (e *HashSignerVerifier) GetVerificationPolicy() *protoblocktx.NamespacePolicy {
132133
return &protoblocktx.NamespacePolicy{
133-
Scheme: e.scheme,
134-
PublicKey: e.pubKey,
134+
Scheme: e.scheme,
135+
Policy: e.pubKey,
135136
}
136137
}
137138

loadgen/workload/tx_builder.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -89,14 +89,14 @@ func (txb *TxBuilder) makeTx(optionalTxID *string, blockTx *protoblocktx.Tx) *pr
8989

9090
// 2. Signs the TX:
9191
switch {
92-
case blockTx.Signatures != nil:
92+
case len(blockTx.SignatureSets) > 0:
9393
// If the TX already have a signature, it doesn't re-sign it.
9494
case txb.TxSigner != nil:
9595
// If TxSigner is given, it is used to sign the TX.
9696
txb.TxSigner.Sign(txID, blockTx)
9797
case txb.TxSigner == nil:
9898
// Otherwise, it puts empty signatures for all namespaces to ensure well-formed TX.
99-
blockTx.Signatures = make([][]byte, len(blockTx.Namespaces))
99+
blockTx.SignatureSets = make([]*protoblocktx.SignatureSet, len(blockTx.Namespaces))
100100
}
101101

102102
// 3. Serializes the envelope's payload.

0 commit comments

Comments
 (0)