Skip to content
Open
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
738 changes: 561 additions & 177 deletions api/protoblocktx/block_tx.pb.go

Large diffs are not rendered by default.

50 changes: 45 additions & 5 deletions api/protoblocktx/block_tx.proto
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,14 @@ option go_package = "github.com/hyperledger/fabric-x-committer/api/protoblocktx"

package protoblocktx;

// Represents a transaction in the blockchain.
message Tx {
repeated TxNamespace namespaces = 1; // Namespaces associated with the transaction.
repeated bytes signatures = 2; // Signature per namespace.
// A list of namespaces that define the transaction's scope.
repeated TxNamespace namespaces = 1;

// A list of endorsements.
// IMPORTANT: This list MUST be the same size as the namespaces list.
// The Endorsement at index i corresponds to the namespace at index i.
repeated Endorsements endorsements = 2;
}

// Represents a namespace within a transaction.
Expand Down Expand Up @@ -44,9 +48,45 @@ message Write {
bytes value = 2; // The value associated with the key being written.
}

// Endorsements holds all the signatures that correspond to a single namespace
// in the transaction's namespaces list.
message Endorsements {
// The list of individual signatures for the corresponding namespace.
repeated EndorsementWithIdentity endorsements_with_identity = 1;
}

// EndorsementWithIdentity bundles a single signature with the identity of its creator.
message EndorsementWithIdentity {
// The actual cryptographic signature bytes.
bytes endorsement = 1;

// The identity of the creator who produced the signature, i.e., the endorsement.
Identity identity = 2;
}

message Identity {
// The identifier of the associated membership service provider
string msp_id = 1;

oneof creator {
// The full raw bytes of the creator's certificate (e.g., an X.509 certificate).
bytes certificate = 2;

// An identifier for a certificate that is pre-stored or known by the committer.
string certificate_id = 3;
}
}

// Represents a namespace policy.
message NamespacePolicy {
string scheme = 1; // The scheme for signature verification.
oneof rule {
ThresholdRule threshold_rule = 1;
bytes signature_rule = 2;
}
}

message ThresholdRule {
string scheme = 1; // The scheme for signature verification.
bytes public_key = 2; // The public key for signature verification.
}

Expand Down Expand Up @@ -78,7 +118,7 @@ message NamespacePolicies {

message PolicyItem {
string namespace = 1;
bytes policy = 2;
NamespacePolicy policy = 2;
uint64 version = 3;
}

Expand Down
6 changes: 3 additions & 3 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ go 1.24.3

require (
github.com/cenkalti/backoff/v4 v4.3.0
github.com/cockroachdb/errors v1.11.3
github.com/consensys/gnark-crypto v0.18.1
github.com/cockroachdb/errors v1.12.0
github.com/consensys/gnark-crypto v0.18.0
github.com/docker/docker v28.0.0+incompatible
github.com/docker/go-connections v0.5.0
github.com/fsouza/go-dockerclient v1.12.0
Expand All @@ -19,7 +19,7 @@ require (
github.com/google/uuid v1.6.0
github.com/hyperledger/fabric-lib-go v1.1.3-0.20240523144151-25edd1eaf5f5
github.com/hyperledger/fabric-protos-go-apiv2 v0.3.7
github.com/hyperledger/fabric-x-common v0.0.0-20251023133631-047a3c32c228
github.com/hyperledger/fabric-x-common v0.0.0-20251027142320-96a137a5adfb
github.com/jackc/puddle v1.3.0
github.com/mitchellh/mapstructure v1.5.0
github.com/onsi/gomega v1.34.2
Expand Down
12 changes: 6 additions & 6 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -675,14 +675,14 @@ github.com/cncf/xds/go v0.0.0-20230105202645-06c439db220b/go.mod h1:eXthEFrGJvWH
github.com/cncf/xds/go v0.0.0-20230310173818-32f1caf87195/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/cockroachdb/apd v1.1.0 h1:3LFP3629v+1aKXU5Q37mxmRxX/pIu1nijXydLShEq5I=
github.com/cockroachdb/apd v1.1.0/go.mod h1:8Sl8LxpKi29FqWXR16WEFZRNSz3SoPzUzeMeY4+DwBQ=
github.com/cockroachdb/errors v1.11.3 h1:5bA+k2Y6r+oz/6Z/RFlNeVCesGARKuC6YymtcDrbC/I=
github.com/cockroachdb/errors v1.11.3/go.mod h1:m4UIW4CDjx+R5cybPsNrRbreomiFqt8o1h1wUVazSd8=
github.com/cockroachdb/errors v1.12.0 h1:d7oCs6vuIMUQRVbi6jWWWEJZahLCfJpnJSVobd1/sUo=
github.com/cockroachdb/errors v1.12.0/go.mod h1:SvzfYNNBshAVbZ8wzNc/UPK3w1vf0dKDUP41ucAIf7g=
github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b h1:r6VH0faHjZeQy818SGhaone5OnYfxFR/+AzdY3sf5aE=
github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b/go.mod h1:Vz9DsVWQQhf3vs21MhPMZpMGSht7O/2vFW2xusFUVOs=
github.com/cockroachdb/redact v1.1.5 h1:u1PMllDkdFfPWaNGMyLD1+so+aq3uUItthCFqzwPJ30=
github.com/cockroachdb/redact v1.1.5/go.mod h1:BVNblN9mBWFyMyqK1k3AAiSxhvhfK2oOZZ2lK+dpvRg=
github.com/consensys/gnark-crypto v0.18.1 h1:RyLV6UhPRoYYzaFnPQA4qK3DyuDgkTgskDdoGqFt3fI=
github.com/consensys/gnark-crypto v0.18.1/go.mod h1:L3mXGFTe1ZN+RSJ+CLjUt9x7PNdx8ubaYfDROyp2Z8c=
github.com/consensys/gnark-crypto v0.18.0 h1:vIye/FqI50VeAr0B3dx+YjeIvmc3LWz4yEfbWBpTUf0=
github.com/consensys/gnark-crypto v0.18.0/go.mod h1:L3mXGFTe1ZN+RSJ+CLjUt9x7PNdx8ubaYfDROyp2Z8c=
github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I=
github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo=
github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
Expand Down Expand Up @@ -918,8 +918,8 @@ github.com/hyperledger/fabric-lib-go v1.1.3-0.20240523144151-25edd1eaf5f5 h1:RPW
github.com/hyperledger/fabric-lib-go v1.1.3-0.20240523144151-25edd1eaf5f5/go.mod h1:SHNCq8AB0VpHAmvJEtdbzabv6NNV1F48JdmDihasBjc=
github.com/hyperledger/fabric-protos-go-apiv2 v0.3.7 h1:sQ5qv8vQQfwewa1JlCiSCC8dLElmaU2/frLolpgibEY=
github.com/hyperledger/fabric-protos-go-apiv2 v0.3.7/go.mod h1:bJnwzfv03oZQeCc863pdGTDgf5nmCy6Za3RAE7d2XsQ=
github.com/hyperledger/fabric-x-common v0.0.0-20251023133631-047a3c32c228 h1:JdVLvE5ExlHvGL2LuaX3IQLo+7ZExsJhPkDutmNCJEU=
github.com/hyperledger/fabric-x-common v0.0.0-20251023133631-047a3c32c228/go.mod h1:eztTd6MwzVOZtlWcOXWZepDBK/pQz3c3epu91BXAp6o=
github.com/hyperledger/fabric-x-common v0.0.0-20251027142320-96a137a5adfb h1:oh/k9KIvG/GOuBC92LaEZoI6IlFM91inQ7quoAV8L6w=
github.com/hyperledger/fabric-x-common v0.0.0-20251027142320-96a137a5adfb/go.mod h1:5C4Ab/S56VXzP9BpePfbKr3Clmi1t1soKMThJeGBSIQ=
github.com/iancoleman/strcase v0.2.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho=
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
Expand Down
4 changes: 2 additions & 2 deletions integration/runner/runtime.go
Original file line number Diff line number Diff line change
Expand Up @@ -409,9 +409,9 @@ func (c *CommitterRuntime) MakeAndSendTransactionsToOrderer(
Namespaces: namespaces,
}
if expectedStatus != nil && expectedStatus[i] == protoblocktx.Status_ABORTED_SIGNATURE_INVALID {
tx.Signatures = make([][]byte, len(namespaces))
tx.Endorsements = make([]*protoblocktx.Endorsements, len(namespaces))
for nsIdx := range namespaces {
tx.Signatures[nsIdx] = []byte("dummy")
tx.Endorsements[nsIdx] = test.CreateEndorsementsForThresholdRule([]byte("dummy"))[0]
}
}
txs[i] = c.TxBuilder.MakeTx(tx)
Expand Down
2 changes: 1 addition & 1 deletion integration/test/config_update_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ func TestConfigUpdate(t *testing.T) {
ordererEnv.SubmitConfigBlock(t, &workload.ConfigBlock{
ChannelID: c.SystemConfig.Policy.ChannelID,
OrdererEndpoints: endpoints,
MetaNamespaceVerificationKey: metaPolicy.PublicKey,
MetaNamespaceVerificationKey: metaPolicy.GetThresholdRule().GetPublicKey(),
})
}
submitConfigBlock(ordererEnv.AllRealOrdererEndpoints())
Expand Down
7 changes: 1 addition & 6 deletions loadgen/adapters/sigverifier.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import (

"github.com/cockroachdb/errors"
"golang.org/x/sync/errgroup"
"google.golang.org/protobuf/proto"

"github.com/hyperledger/fabric-x-committer/api/protoblocktx"
"github.com/hyperledger/fabric-x-committer/api/protosigverifierservice"
Expand Down Expand Up @@ -101,15 +100,11 @@ func createUpdate(policy *workload.PolicyProfile) (*protosigverifierservice.Upda
if ns == types.MetaNamespaceID {
continue
}
policyBytes, err := proto.Marshal(p.GetVerificationPolicy())
if err != nil {
return nil, errors.Wrap(err, "failed to serialize policy")
}
updateMsg.NamespacePolicies.Policies = append(
updateMsg.NamespacePolicies.Policies,
&protoblocktx.PolicyItem{
Namespace: ns,
Policy: policyBytes,
Policy: p.GetVerificationPolicy(),
},
)
}
Expand Down
6 changes: 3 additions & 3 deletions loadgen/workload/config_tx.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,12 +92,12 @@ func CreateConfigBlock(policy *PolicyProfile) (*common.Block, error) {
MetaNamespaceVerificationKey: policyNamespaceSigner.pubKey,
OrdererEndpoints: policy.OrdererEndpoints,
ChannelID: policy.ChannelID,
})
}, genesisconfig.TwoOrgsSampleFabricX)
}

// CreateDefaultConfigBlock creates a config block with default values.
func CreateDefaultConfigBlock(conf *ConfigBlock) (*common.Block, error) {
configBlock := genesisconfig.Load(genesisconfig.SampleFabricX, configtest.GetDevConfigDir())
func CreateDefaultConfigBlock(conf *ConfigBlock, profileName string) (*common.Block, error) {
configBlock := genesisconfig.Load(profileName, configtest.GetDevConfigDir())
tlsCertPath := filepath.Join(configtest.GetDevConfigDir(), "msp", "tlscacerts", "tlsroot.pem")
for _, consenter := range configBlock.Orderer.ConsenterMapping {
consenter.Identity = tlsCertPath
Expand Down
7 changes: 4 additions & 3 deletions loadgen/workload/conflicts.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
"math/rand"

"github.com/hyperledger/fabric-x-committer/api/protoblocktx"
"github.com/hyperledger/fabric-x-committer/utils/test"
)

// Dependency types.
Expand Down Expand Up @@ -61,9 +62,9 @@ func newSignTxModifier(rnd *rand.Rand, profile *Profile) *signTxModifier {
func (g *signTxModifier) Modify(tx *protoblocktx.Tx) {
if g.invalidSignGenerator.Next() {
// Pre-assigning prevents TxBuilder from re-signing the TX.
tx.Signatures = make([][]byte, len(tx.Namespaces))
for i := range tx.Namespaces {
tx.Signatures[i] = g.invalidSignature
tx.Endorsements = make([]*protoblocktx.Endorsements, len(tx.Namespaces))
for i := range len(tx.Namespaces) {
tx.Endorsements[i] = test.CreateEndorsementsForThresholdRule(g.invalidSignature)[0]
}
}
}
Expand Down
14 changes: 9 additions & 5 deletions loadgen/workload/sign.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import (
"github.com/hyperledger/fabric-x-committer/utils/logging"
"github.com/hyperledger/fabric-x-committer/utils/signature"
"github.com/hyperledger/fabric-x-committer/utils/signature/sigtest"
"github.com/hyperledger/fabric-x-committer/utils/test"
)

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

// Sign signs a TX.
func (e *TxSignerVerifier) Sign(txID string, tx *protoblocktx.Tx) {
tx.Signatures = make([][]byte, len(tx.Namespaces))
tx.Endorsements = make([]*protoblocktx.Endorsements, len(tx.Namespaces))
for nsIndex, ns := range tx.Namespaces {
signer, ok := e.HashSigners[ns.NsId]
if !ok {
continue
}
tx.Signatures[nsIndex] = signer.Sign(txID, tx, nsIndex)
tx.Endorsements[nsIndex] = test.CreateEndorsementsForThresholdRule(signer.Sign(txID, tx, nsIndex))[0]
}
}

// Verify verifies a signature on the transaction.
func (e *TxSignerVerifier) Verify(txID string, tx *protoblocktx.Tx) bool {
if len(tx.Signatures) < len(tx.Namespaces) {
if len(tx.Endorsements) < len(tx.Namespaces) {
return false
}

Expand Down Expand Up @@ -130,8 +131,11 @@ func (e *HashSignerVerifier) Verify(txID string, tx *protoblocktx.Tx, nsIndex in
// GetVerificationPolicy returns the verification policy.
func (e *HashSignerVerifier) GetVerificationPolicy() *protoblocktx.NamespacePolicy {
return &protoblocktx.NamespacePolicy{
Scheme: e.scheme,
PublicKey: e.pubKey,
Rule: &protoblocktx.NamespacePolicy_ThresholdRule{
ThresholdRule: &protoblocktx.ThresholdRule{
Scheme: e.scheme, PublicKey: e.pubKey,
},
},
}
}

Expand Down
4 changes: 2 additions & 2 deletions loadgen/workload/tx_builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -89,14 +89,14 @@ func (txb *TxBuilder) makeTx(optionalTxID *string, blockTx *protoblocktx.Tx) *pr

// 2. Signs the TX:
switch {
case blockTx.Signatures != nil:
case len(blockTx.Endorsements) > 0:
// If the TX already have a signature, it doesn't re-sign it.
case txb.TxSigner != nil:
// If TxSigner is given, it is used to sign the TX.
txb.TxSigner.Sign(txID, blockTx)
case txb.TxSigner == nil:
// Otherwise, it puts empty signatures for all namespaces to ensure well-formed TX.
blockTx.Signatures = make([][]byte, len(blockTx.Namespaces))
blockTx.Endorsements = make([]*protoblocktx.Endorsements, len(blockTx.Namespaces))
}

// 3. Serializes the envelope's payload.
Expand Down
2 changes: 1 addition & 1 deletion mock/sigverifier.go
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ func (m *SigVerifier) sendResponseBatch(
}
status := protoblocktx.Status_COMMITTED
isConfig := len(req.Tx.Namespaces) == 1 && req.Tx.Namespaces[0].NsId == types.ConfigNamespaceID
if len(req.Tx.Signatures) == 0 && !isConfig {
if len(req.Tx.Endorsements) == 0 && !isConfig {
status = protoblocktx.Status_ABORTED_SIGNATURE_INVALID
}
respBatch.Responses = append(respBatch.Responses, &protosigverifierservice.Response{
Expand Down
3 changes: 2 additions & 1 deletion mock/test_exports.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (
"testing"

"github.com/hyperledger/fabric-protos-go-apiv2/common"
"github.com/hyperledger/fabric-x-common/internaltools/configtxgen/genesisconfig"
"github.com/stretchr/testify/require"
"google.golang.org/grpc"

Expand Down Expand Up @@ -179,7 +180,7 @@ func (e *OrdererTestEnv) SubmitConfigBlock(t *testing.T, conf *workload.ConfigBl
if conf.MetaNamespaceVerificationKey == nil {
conf.MetaNamespaceVerificationKey = e.TestConfig.MetaNamespaceVerificationKey
}
configBlock, err := workload.CreateDefaultConfigBlock(conf)
configBlock, err := workload.CreateDefaultConfigBlock(conf, genesisconfig.TwoOrgsSampleFabricX)
require.NoError(t, err)
e.Orderer.SubmitBlock(t.Context(), configBlock)
return configBlock
Expand Down
Loading