From ba3186a26c2e1c40762b0cd0d2d2250d46ed7630 Mon Sep 17 00:00:00 2001 From: Hagar Meir Date: Wed, 15 Oct 2025 12:04:59 +0300 Subject: [PATCH 1/3] add metadata to common block Signed-off-by: Hagar Meir --- node/assembler/oba_utils_test.go | 11 +++++++++ node/consensus/consensus.go | 25 +++++++++++++++----- node/delivery/consensus_ba_deliver_client.go | 19 ++++++++++----- node/ledger/assembler_ledger.go | 2 +- 4 files changed, 44 insertions(+), 13 deletions(-) diff --git a/node/assembler/oba_utils_test.go b/node/assembler/oba_utils_test.go index bd7d8275..a10fac0c 100644 --- a/node/assembler/oba_utils_test.go +++ b/node/assembler/oba_utils_test.go @@ -12,6 +12,7 @@ import ( "github.com/hyperledger/fabric-x-orderer/common/types" "github.com/hyperledger/fabric-x-orderer/common/utils" "github.com/hyperledger/fabric-x-orderer/node/consensus/state" + "github.com/hyperledger/fabric-x-orderer/node/ledger" "github.com/hyperledger/fabric-protos-go-apiv2/common" "github.com/hyperledger/fabric/protoutil" @@ -65,6 +66,16 @@ func (obac *OrderedBatchAttestationCreator) Append(batchId types.BatchID, decisi BatchCount: batchCount, }, } + blockMetadata, err := ledger.AssemblerBlockMetadataToBytes(batchId, &state.OrderingInformation{DecisionNum: decisionNum, BatchCount: batchCount, BatchIndex: batchIndex}, 0) + if err != nil { + panic("Failed to invoke AssemblerBlockMetadataToBytes") + } + var metadataContents [][]byte + for i := 0; i < len(common.BlockMetadataIndex_name); i++ { + metadataContents = append(metadataContents, []byte{}) + } + ba.OrderingInformation.CommonBlock.Metadata = &common.BlockMetadata{Metadata: metadataContents} + ba.OrderingInformation.CommonBlock.Metadata.Metadata[common.BlockMetadataIndex_ORDERER] = blockMetadata obac.headerHash = protoutil.BlockHeaderHash(ba.OrderingInformation.CommonBlock.Header) obac.prevBa = ba return ba diff --git a/node/consensus/consensus.go b/node/consensus/consensus.go index aa60b06f..d78ed16d 100644 --- a/node/consensus/consensus.go +++ b/node/consensus/consensus.go @@ -28,6 +28,7 @@ import ( "github.com/hyperledger/fabric-x-orderer/node/consensus/badb" "github.com/hyperledger/fabric-x-orderer/node/consensus/state" "github.com/hyperledger/fabric-x-orderer/node/delivery" + "github.com/hyperledger/fabric-x-orderer/node/ledger" protos "github.com/hyperledger/fabric-x-orderer/node/protos/comm" "github.com/hyperledger/fabric/protoutil" "github.com/pkg/errors" @@ -240,6 +241,8 @@ func (c *Consensus) VerifyProposal(proposal smartbft_types.Proposal) ([]smartbft return nil, fmt.Errorf("proposed common block header number %d in index %d isn't equal to computed number %d", hdr.AvailableCommonBlocks[i].Header.Number, i, lastBlockNumber) } + // TODO add metadata verification + } for i, availableBlock := range hdr.AvailableBlocks { @@ -321,7 +324,7 @@ func (c *Consensus) VerifySignature(signature smartbft_types.Signature) error { // VerificationSequence returns the current verification sequence // (from SmartBFT API) func (c *Consensus) VerificationSequence() uint64 { - return 0 + return 0 // TODO save current verification sequence and return it here } // RequestsFromProposal returns from the given proposal the included requests' info @@ -444,6 +447,11 @@ func (c *Consensus) AssembleProposal(metadata []byte, requests [][]byte) smartbf lastBlockNumber := lastCommonBlockHeader.Number prevHash := protoutil.BlockHeaderHash(lastCommonBlockHeader) + md := &smartbftprotos.ViewMetadata{} + if err := proto.Unmarshal(metadata, md); err != nil { + panic(err) + } + c.Logger.Infof("Creating proposal with %d attestations", len(attestations)) availableBlocks := make([]state.AvailableBlock, len(attestations)) @@ -459,6 +467,16 @@ func (c *Consensus) AssembleProposal(metadata []byte, requests [][]byte) smartbf lastBlockNumber++ availableCommonBlocks[i] = protoutil.NewBlock(lastBlockNumber, prevHash) availableCommonBlocks[i].Header.DataHash = ba[0].Digest() + blockMetadata, err := ledger.AssemblerBlockMetadataToBytes(ba[0], &state.OrderingInformation{DecisionNum: arma_types.DecisionNum(md.LatestSequence), BatchCount: len(attestations), BatchIndex: i}, 0) + if err != nil { + c.Logger.Panicf("Failed to invoke AssemblerBlockMetadataToBytes: %s", err) + } + var metadataContents [][]byte + for i := 0; i < len(common.BlockMetadataIndex_name); i++ { + metadataContents = append(metadataContents, []byte{}) + } + availableCommonBlocks[i].Metadata = &common.BlockMetadata{Metadata: metadataContents} + availableCommonBlocks[i].Metadata.Metadata[common.BlockMetadataIndex_ORDERER] = blockMetadata hdr.Number = lastBlockNumber hdr.PrevHash = prevHash prevHash = protoutil.BlockHeaderHash(availableCommonBlocks[i].Header) @@ -469,11 +487,6 @@ func (c *Consensus) AssembleProposal(metadata []byte, requests [][]byte) smartbf newState.AppContext = protoutil.MarshalOrPanic(availableCommonBlocks[len(attestations)-1].Header) } - md := &smartbftprotos.ViewMetadata{} - if err := proto.Unmarshal(metadata, md); err != nil { - panic(err) - } - reqs := arma_types.BatchedRequests(requests) return smartbft_types.Proposal{ diff --git a/node/delivery/consensus_ba_deliver_client.go b/node/delivery/consensus_ba_deliver_client.go index f29b9e80..c9203e7c 100644 --- a/node/delivery/consensus_ba_deliver_client.go +++ b/node/delivery/consensus_ba_deliver_client.go @@ -111,19 +111,26 @@ func (cr *ConsensusBAReplicator) Replicate() <-chan types.OrderedBatchAttestatio cr.logger.Panicf("Failed extracting ordered batch attestation from decision: %s", err2) } - cr.logger.Infof("Decision %d, with %d AvailableBlocks", block.GetHeader().GetNumber(), len(header.AvailableBlocks)) - for index, ab := range header.AvailableBlocks { - cr.logger.Infof("BA index: %d; BatchID: %s; BA block header: %s; BA block signers: %+v", index, types.BatchIDToString(ab.Batch), ab.Header.String(), signersFromSigs(sigs[index])) + cr.logger.Infof("Decision %d, with %d AvailableCommonBlocks", block.GetHeader().GetNumber(), len(header.AvailableCommonBlocks)) + for index, acb := range header.AvailableCommonBlocks { + + primary, shard, seq, _, _, _, _, err := ledger.AssemblerBlockMetadataFromBytes(acb.Metadata.Metadata[common.BlockMetadataIndex_ORDERER]) + if err != nil { + cr.logger.Panicf("Failed extracting info from metadata: %s", err) + } + + acbBatch := state.NewAvailableBatch(primary, shard, seq, acb.Header.DataHash) + + cr.logger.Infof("BA index: %d; BatchID: %s; Common Block: %s; BA block signers: %+v", index, types.BatchIDToString(acbBatch), types.CommonBlockToString(acb), signersFromSigs(sigs[index])) abo := &state.AvailableBatchOrdered{ - AvailableBatch: ab.Batch, + AvailableBatch: acbBatch, OrderingInformation: &state.OrderingInformation{ CommonBlock: header.AvailableCommonBlocks[index], - BlockHeader: ab.Header, Signatures: sigs[index], DecisionNum: header.Num, BatchIndex: index, - BatchCount: len(header.AvailableBlocks), + BatchCount: len(header.AvailableCommonBlocks), }, } diff --git a/node/ledger/assembler_ledger.go b/node/ledger/assembler_ledger.go index 35861a85..9a80b23d 100644 --- a/node/ledger/assembler_ledger.go +++ b/node/ledger/assembler_ledger.go @@ -137,7 +137,7 @@ func (l *AssemblerLedger) Append(batch types.Batch, orderingInfo types.OrderingI t1 := time.Now() defer func() { l.Logger.Infof("Appended block %d of %d requests to ledger in %v", - ordInfo.BlockHeader.Number, len(batch.Requests()), time.Since(t1)) + ordInfo.CommonBlock.Header.Number, len(batch.Requests()), time.Since(t1)) }() block := &common.Block{ From 0b93049ccf80c9d0fd39f432457bae99d9612fed Mon Sep 17 00:00:00 2001 From: Hagar Meir Date: Wed, 15 Oct 2025 15:00:29 +0300 Subject: [PATCH 2/3] verify common block metadata in proposal Signed-off-by: Hagar Meir --- node/consensus/consensus.go | 13 ++++++++++++- node/consensus/consensus_builder.go | 21 ++++++++++++++++++--- node/consensus/consensus_test.go | 13 ++++++++++++- 3 files changed, 42 insertions(+), 5 deletions(-) diff --git a/node/consensus/consensus.go b/node/consensus/consensus.go index d78ed16d..877afde0 100644 --- a/node/consensus/consensus.go +++ b/node/consensus/consensus.go @@ -241,7 +241,18 @@ func (c *Consensus) VerifyProposal(proposal smartbft_types.Proposal) ([]smartbft return nil, fmt.Errorf("proposed common block header number %d in index %d isn't equal to computed number %d", hdr.AvailableCommonBlocks[i].Header.Number, i, lastBlockNumber) } - // TODO add metadata verification + blockMetadata, err := ledger.AssemblerBlockMetadataToBytes(ba[0], &state.OrderingInformation{DecisionNum: arma_types.DecisionNum(md.LatestSequence), BatchCount: len(attestations), BatchIndex: i}, 0) + if err != nil { + c.Logger.Panicf("Failed to invoke AssemblerBlockMetadataToBytes: %s", err) + } + + if hdr.AvailableCommonBlocks[i].Metadata == nil || hdr.AvailableCommonBlocks[i].Metadata.Metadata == nil { + return nil, fmt.Errorf("proposed common block metadata in index %d is nil", i) + } + + if !bytes.Equal(blockMetadata, hdr.AvailableCommonBlocks[i].Metadata.Metadata[common.BlockMetadataIndex_ORDERER]) { + return nil, fmt.Errorf("proposed common block metadata in index %d isn't equal to computed metadata", i) + } } diff --git a/node/consensus/consensus_builder.go b/node/consensus/consensus_builder.go index d02a9334..62943711 100644 --- a/node/consensus/consensus_builder.go +++ b/node/consensus/consensus_builder.go @@ -261,7 +261,7 @@ func initialStateFromConfig(config *config.ConsenterNodeConfig) *state.State { return &initState } -func appendGenesisBlock(genesisBlock *common.Block, initState *state.State, ledger *ledger.ConsensusLedger) { +func appendGenesisBlock(genesisBlock *common.Block, initState *state.State, consensusLedger *ledger.ConsensusLedger) { genesisBlocks := make([]state.AvailableBlock, 1) genesisDigest := protoutil.ComputeBlockDataHash(genesisBlock.GetData()) @@ -283,10 +283,25 @@ func appendGenesisBlock(genesisBlock *common.Block, initState *state.State, ledg initState.AppContext = protoutil.MarshalOrPanic(lastCommonBlockHeader) + availableCommonBlocks := []*common.Block{genesisBlock} + + var metadataContents [][]byte + for i := 0; i < len(common.BlockMetadataIndex_name); i++ { + metadataContents = append(metadataContents, []byte{}) + } + availableCommonBlocks[0].Metadata = &common.BlockMetadata{Metadata: metadataContents} + + blockMetadata, err := ledger.AssemblerBlockMetadataToBytes(state.NewAvailableBatch(0, arma_types.ShardIDConsensus, 0, genesisDigest), &state.OrderingInformation{DecisionNum: 0, BatchCount: 1, BatchIndex: 0}, 0) + if err != nil { + panic("failed to invoke AssemblerBlockMetadataToBytes") + } + + availableCommonBlocks[0].Metadata.Metadata[common.BlockMetadataIndex_ORDERER] = blockMetadata + genesisProposal := smartbft_types.Proposal{ Payload: protoutil.MarshalOrPanic(genesisBlock), Header: (&state.Header{ - AvailableCommonBlocks: []*common.Block{genesisBlock}, + AvailableCommonBlocks: availableCommonBlocks, AvailableBlocks: genesisBlocks, State: initState, Num: 0, @@ -294,7 +309,7 @@ func appendGenesisBlock(genesisBlock *common.Block, initState *state.State, ledg Metadata: nil, } - ledger.Append(state.DecisionToBytes(genesisProposal, nil)) + consensusLedger.Append(state.DecisionToBytes(genesisProposal, nil)) } func (c *Consensus) clientConfig() comm.ClientConfig { diff --git a/node/consensus/consensus_test.go b/node/consensus/consensus_test.go index 63f6337a..52bec9ef 100644 --- a/node/consensus/consensus_test.go +++ b/node/consensus/consensus_test.go @@ -717,9 +717,20 @@ func TestVerifyProposal(t *testing.T) { latestBlockHeader.DataHash = baf123id1p1s1.Digest() latestBlockHeader.PreviousHash = protoutil.BlockHeaderHash(initialAppContext) - header.AvailableBlocks = []state.AvailableBlock{{Header: &state.BlockHeader{Number: latestBlockHeader.Number, PrevHash: latestBlockHeader.PreviousHash, Digest: latestBlockHeader.DataHash}, Batch: state.NewAvailableBatch(baf123id1p1s1.Primary(), baf123id1p1s1.Shard(), baf123id1p1s1.Seq(), baf123id1p1s1.Digest())}} + ab := state.NewAvailableBatch(baf123id1p1s1.Primary(), baf123id1p1s1.Shard(), baf123id1p1s1.Seq(), baf123id1p1s1.Digest()) + + header.AvailableBlocks = []state.AvailableBlock{{Header: &state.BlockHeader{Number: latestBlockHeader.Number, PrevHash: latestBlockHeader.PreviousHash, Digest: latestBlockHeader.DataHash}, Batch: ab}} header.AvailableCommonBlocks = []*common.Block{{Header: latestBlockHeader}} + var metadataContents [][]byte + for i := 0; i < len(common.BlockMetadataIndex_name); i++ { + metadataContents = append(metadataContents, []byte{}) + } + header.AvailableCommonBlocks[0].Metadata = &common.BlockMetadata{Metadata: metadataContents} + blockMetadata, err := ledger.AssemblerBlockMetadataToBytes(ab, &state.OrderingInformation{DecisionNum: 0, BatchCount: 1, BatchIndex: 0}, 0) + require.Nil(t, err) + header.AvailableCommonBlocks[0].Metadata.Metadata[common.BlockMetadataIndex_ORDERER] = blockMetadata + newState := initialState newState.AppContext = protoutil.MarshalOrPanic(latestBlockHeader) From 3b7aa308af73b07dd2319fcc4b6adac8b9c58e33 Mon Sep 17 00:00:00 2001 From: Hagar Meir Date: Thu, 16 Oct 2025 10:46:42 +0300 Subject: [PATCH 3/3] AvailableBlocks --> AvailableCommonBlocks Signed-off-by: Hagar Meir --- node/delivery/utils.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/node/delivery/utils.go b/node/delivery/utils.go index 96a9da4f..4552890b 100644 --- a/node/delivery/utils.go +++ b/node/delivery/utils.go @@ -55,7 +55,7 @@ func extractHeaderAndSigsFromBlock(block *common.Block) (*state.Header, [][]smar return stateHeader, sigs, nil } - sigs, err := state.UnpackBlockHeaderSigs(compoundSigs, len(stateHeader.AvailableBlocks)) + sigs, err := state.UnpackBlockHeaderSigs(compoundSigs, len(stateHeader.AvailableCommonBlocks)) if err != nil { return nil, nil, errors.Wrapf(err, "failed to extract header signatures from compound signature, block %d", block.GetHeader().GetNumber()) }