Skip to content

Commit f8dd7a3

Browse files
committed
[FAB-2024] Add valid indicator to GetTransactionById
When clients retrieve a transaction from ledger, they need to know whether the transaction was validated or invalidated by committing peer. GetTransactionByID API needs to retrieve the transaction Envelope from block storage, and return it to a client, and indicate whether the transaction was validated or invalidated by committing peer. So that the originally submitted transaction Envelope is not modified, a new ProcessedTransaction wrapper is returned. Also removed InvalidTransaction, since it is not used. Change-Id: I7a4ec2b56b120f5df4ef18f0df415bab1a7dc9d1 Signed-off-by: denyeart <[email protected]>
1 parent d58349a commit f8dd7a3

File tree

7 files changed

+104
-85
lines changed

7 files changed

+104
-85
lines changed

core/ledger/kvledger/kv_ledger.go

+18-2
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ import (
2929
"github.com/hyperledger/fabric/core/ledger/kvledger/txmgmt/txmgr/lockbasedtxmgr"
3030
"github.com/hyperledger/fabric/core/ledger/ledgerconfig"
3131
"github.com/hyperledger/fabric/protos/common"
32+
"github.com/hyperledger/fabric/protos/peer"
3233
logging "github.com/op/go-logging"
3334
)
3435

@@ -199,8 +200,23 @@ func recommitLostBlocks(l *kvLedger, savepoint uint64, blockHeight uint64, recov
199200
}
200201

201202
// GetTransactionByID retrieves a transaction by id
202-
func (l *kvLedger) GetTransactionByID(txID string) (*common.Envelope, error) {
203-
return l.blockStore.RetrieveTxByID(txID)
203+
func (l *kvLedger) GetTransactionByID(txID string) (*peer.ProcessedTransaction, error) {
204+
205+
tranEnv, err := l.blockStore.RetrieveTxByID(txID)
206+
if err != nil {
207+
return nil, err
208+
}
209+
210+
// Hardocde to Valid:true for now
211+
processedTran := &peer.ProcessedTransaction{TransactionEnvelope: tranEnv, Valid: true}
212+
213+
// TODO subsequent changeset will retrieve validation bit array on the block to indicate
214+
// whether the tran was validated or invalidated. It is possible to retreive both the tran
215+
// and the block (with bit array) from storage and combine the results. But it would be
216+
// more efficient to refactor block storage to retrieve the tran and the validation bit
217+
// in one operation.
218+
219+
return processedTran, nil
204220
}
205221

206222
// GetBlockchainInfo returns basic info about blockchain

core/ledger/kvledger/kv_ledger_test.go

+15
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import (
2626
"github.com/hyperledger/fabric/core/ledger/ledgerconfig"
2727
ledgertestutil "github.com/hyperledger/fabric/core/ledger/testutil"
2828
"github.com/hyperledger/fabric/protos/common"
29+
putils "github.com/hyperledger/fabric/protos/utils"
2930
"github.com/stretchr/testify/assert"
3031
)
3132

@@ -81,6 +82,20 @@ func TestKVLedgerBlockStorage(t *testing.T) {
8182

8283
b2, _ = ledger.GetBlockByNumber(2)
8384
testutil.AssertEquals(t, b2, block2)
85+
86+
// get the tran id from the 2nd block, then use it to test GetTransactionByID()
87+
txEnvBytes2 := block2.Data.Data[0]
88+
txEnv2, err := putils.GetEnvelopeFromBlock(txEnvBytes2)
89+
testutil.AssertNoError(t, err, "Error upon GetEnvelopeFromBlock")
90+
payload2, err := putils.GetPayload(txEnv2)
91+
testutil.AssertNoError(t, err, "Error upon GetPayload")
92+
txID2 := payload2.Header.ChannelHeader.TxId
93+
processedTran2, err := ledger.GetTransactionByID(txID2)
94+
testutil.AssertNoError(t, err, "Error upon GetTransactionByID")
95+
// get the tran envelope from the retrieved ProcessedTransaction
96+
retrievedTxEnv2 := processedTran2.TransactionEnvelope
97+
testutil.AssertEquals(t, retrievedTxEnv2, txEnv2)
98+
8499
}
85100

86101
func TestKVLedgerDBRecovery(t *testing.T) {

core/ledger/ledger_interface.go

+2-1
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ package ledger
1919
import (
2020
commonledger "github.com/hyperledger/fabric/common/ledger"
2121
"github.com/hyperledger/fabric/protos/common"
22+
"github.com/hyperledger/fabric/protos/peer"
2223
)
2324

2425
// PeerLedgerProvider provides handle to ledger instances
@@ -40,7 +41,7 @@ type PeerLedgerProvider interface {
4041
type PeerLedger interface {
4142
commonledger.Ledger
4243
// GetTransactionByID retrieves a transaction by id
43-
GetTransactionByID(txID string) (*common.Envelope, error)
44+
GetTransactionByID(txID string) (*peer.ProcessedTransaction, error)
4445
// GetBlockByHash returns a block given it's hash
4546
GetBlockByHash(blockHash []byte) (*common.Block, error)
4647
// NewTxSimulator gives handle to a transaction simulator.

core/scc/qscc/querier.go

+3-4
Original file line numberDiff line numberDiff line change
@@ -199,14 +199,13 @@ func getTransactionByID(vledger ledger.PeerLedger, tid []byte) pb.Response {
199199
if tid == nil {
200200
return shim.Error("Transaction ID must not be nil.")
201201
}
202-
txEnvelope, err := vledger.GetTransactionByID(string(tid))
202+
203+
processedTran, err := vledger.GetTransactionByID(string(tid))
203204
if err != nil {
204205
return shim.Error(fmt.Sprintf("Failed to get transaction with id %s, error %s", string(tid), err))
205206
}
206-
// TODO In the returned transaction, need to replace binary simulation results with a proto
207-
// structure including write set, so that clients know what this transaction wrote
208207

209-
bytes, err := utils.Marshal(txEnvelope)
208+
bytes, err := utils.Marshal(processedTran)
210209
if err != nil {
211210
return shim.Error(err.Error())
212211
}

protos/peer/admin.pb.go

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

protos/peer/transaction.pb.go

+52-69
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

protos/peer/transaction.proto

+13-8
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ package protos;
2222

2323
import "google/protobuf/timestamp.proto";
2424
import "peer/proposal_response.proto";
25+
import "common/common.proto";
2526

2627
// This message is necessary to facilitate the verification of the signature
2728
// (in the signature field) over the bytes of the transaction (in the
@@ -38,14 +39,18 @@ message SignedTransaction {
3839
bytes signature = 2;
3940
}
4041

41-
// This is used to wrap an invalid Transaction with the cause
42-
message InvalidTransaction {
43-
enum Cause {
44-
TX_ID_ALREADY_EXISTS = 0;
45-
RW_CONFLICT_DURING_COMMIT = 1;
46-
}
47-
Transaction transaction = 1;
48-
Cause cause = 2;
42+
// ProcessedTransaction wraps an Envelope that includes a transaction along with an indication
43+
// of whether the transaction was validated or invalidated by committing peer.
44+
// The use case is that GetTransactionByID API needs to retrieve the transaction Envelope
45+
// from block storage, and return it to a client, and indicate whether the transaction
46+
// was validated or invalidated by committing peer. So that the originally submitted
47+
// transaction Envelope is not modified, the ProcessedTransaction wrapper is returned.
48+
message ProcessedTransaction {
49+
// An Envelope which includes a processed transaction
50+
common.Envelope transactionEnvelope = 1;
51+
52+
// An indication of whether the transaction was validated or invalidated by committing peer
53+
bool valid = 2;
4954
}
5055

5156
// The transaction to be sent to the ordering service. A transaction contains

0 commit comments

Comments
 (0)