The Fabric network implementation (fabric.Network) provides integration with Hyperledger Fabric networks using the traditional chaincode-based endorsement model. It leverages the Fabric Smart Client (FSC) to interact with the underlying Hyperledger Fabric network.
The Fabric implementation uses a Token Chaincode deployed on Fabric peers to handle token operations. This chaincode validates token requests, manages token state, and enforces business logic.
graph TB
subgraph "Application Node running FSC/Panurus stack"
App[Application/TTX]
FabricNet[Fabric Network Service]
end
subgraph "Hyperledger Fabric Network"
Peer1[Peer 1<br/>Token Chaincode]
Peer2[Peer 2<br/>Token Chaincode]
Orderer[Ordering Service]
Ledger[Committer]
end
App -->|1. Request Approval| FabricNet
FabricNet -->|2. Endorse Proposal| Peer1
FabricNet -->|2. Endorse Proposal| Peer2
Peer1 -->|3. Endorsement| FabricNet
Peer2 -->|3. Endorsement| FabricNet
FabricNet -->|4. Broadcast Tx| Orderer
Orderer -->|5. Order & Distribute| Ledger
Ledger -->|6. Finality Event| FabricNet
FabricNet -->|7. Notify| App
The Token Chaincode (tcc.TokenChaincode) is a Fabric chaincode that runs on peers and handles all token-related operations.
The chaincode exposes the following functions:
| Function | Purpose | Parameters | Returns |
|---|---|---|---|
invoke |
Process token requests (issue, transfer, redeem) | Token request (transient) | Transaction envelope |
queryPublicParams |
Retrieve public parameters | Public parameters bytes | |
queryTokens |
Query token state | Token IDs | Token data |
areTokensSpent |
Check if tokens are spent | Token IDs, metadata | Boolean array |
queryStates |
Query arbitrary state keys | State keys | State values |
The Token Chaincode must be deployed to the Fabric network before Panurus can operate:
sequenceDiagram
participant Admin as Network Admin
participant Peer as Fabric Peer
participant Orderer as Ordering Service
participant Ledger as Blockchain
Admin->>Peer: Package chaincode
Admin->>Peer: Install chaincode
Admin->>Peer: Approve chaincode definition
Admin->>Orderer: Commit chaincode definition
Orderer->>Ledger: Record chaincode metadata
Ledger-->>Peer: Chaincode ready
Note over Admin,Ledger: Chaincode is now available for invocation
Deployment Steps:
At initialization time, the chaincode loads public parameters and persists them to the setup key on the ledger. The implementation in tcc.TokenChaincode.Init() calls tcc.TokenChaincode.Params(), which resolves the parameters using the following precedence:
PUBLIC_PARAMS_FILE_PATH environment variable is set, tcc.TokenChaincode.ReadParamsFromFile() reads the raw public-parameter bytes from that file and feeds them back as a base64 string.tcc.Params is used. In the source tree this variable is empty by default, but packaging tools replace tcc/params.go with generated content that embeds a base64-encoded blob of the public parameters into the chaincode package itself.This means the token chaincode supports both models:
tcc.ParamsPUBLIC_PARAMS_FILE_PATHtokengen can also generate the token-chaincode package with the public parameters already embedded, by generating a replacement for tcc/params.go from the template in cc.DefaultParams as part of cc.GeneratePackage().
// Simplified initialization flow
func (cc *TokenChaincode) Init(stub shim.ChaincodeStubInterface) *pb.Response {
// Resolve public parameters from file override or built-in Params
ppRaw, err := cc.Params(Params)
// Write the selected parameters to the ledger setup key
w := translator.New(stub.GetTxID(), ...)
w.Write(context.Background(), &SetupAction{SetupParameters: ppRaw})
return shim.Success(nil)
}
The Fabric implementation supports chaincode-based endorsement through the ChaincodeEndorsementService.
sequenceDiagram
participant App as Application
participant Net as Network Service
participant ES as Endorsement Service
participant FSC as Fabric Smart Client
participant Peer as Fabric Peer
App->>Net: RequestApproval(request)
Net->>ES: Endorse(request, signer, txID)
ES->>FSC: NewEndorseView(namespace, "invoke")
ES->>FSC: WithTransient("token_request", request)
ES->>FSC: WithSignerIdentity(signer)
ES->>FSC: WithTxID(txID)
FSC->>Peer: Send proposal
Peer->>Peer: Execute chaincode
Peer->>Peer: Generate RWSet
Peer->>Peer: Sign endorsement
Peer-->>FSC: Endorsement response
FSC-->>ES: Transaction envelope
ES-->>Net: Endorsed envelope
Net-->>App: Endorsed envelope
The chaincode endorsement follows Fabric’s standard endorsement policies:
Example policy: "OR('Org1MSP.peer', 'Org2MSP.peer')" - requires endorsement from either Org1 or Org2.
The Fabric implementation supports two modes for monitoring transaction finality:
Uses a block delivery stream from the peer for real-time finality tracking:
sequenceDiagram
participant App as Application
participant Net as Network Service
participant FM as Finality Manager
participant Peer as Fabric Peer
participant Proc as Block Processor
App->>Net: AddFinalityListener(txID, listener)
Net->>FM: Register listener
loop Block Delivery Stream
Peer->>FM: Deliver block
FM->>Proc: Process block (parallel)
Proc->>Proc: Extract transactions
Proc->>Proc: Check validation codes
Proc->>Proc: Match registered listeners
Proc->>Net: Notify listener(txID, status)
Net->>App: OnStatus(txID, VALID/INVALID)
end
Features:
Uses asynchronous event notifications from the FSC layer:
sequenceDiagram
participant App as Application
participant Net as Network Service
participant FM as Finality Manager
participant FSC as Fabric Smart Client
App->>Net: AddFinalityListener(txID, listener)
Net->>FM: Register listener
FSC->>FSC: Monitor ledger events
FSC->>FM: Transaction event(txID, status)
FM->>Net: Notify listener
Net->>App: OnStatus(txID, VALID/INVALID)
The Fabric implementation monitors the ledger for public parameters updates:
sequenceDiagram
participant Net as Network Service
participant SL as Setup Listener
participant Ledger as Blockchain
participant TMS as TMS Provider
participant DB as Tokens Database
Note over Net,DB: Initialization
Net->>SL: Register setup listener
SL->>Ledger: Monitor setup key
Note over Net,DB: Update Detection
Ledger->>SL: Setup key modified
SL->>SL: Fetch new parameters
SL->>TMS: Update(new params)
SL->>DB: Persist(new params)
Note over Net,DB: SDK synchronized with new parameters
The setup listener watches for changes to a specific ledger key that stores public parameters. This mechanism is based on delivery as the finality path, because setup-key updates are detected from committed ledger events delivered by the peer:
The Fabric implementation provides efficient state querying through the chaincode:
sequenceDiagram
participant App as Application
participant Net as Network Service
participant Ledger as Ledger Service
participant CC as Token Chaincode
participant State as World State
App->>Net: QueryTokens(tokenIDs)
Net->>Ledger: GetStates(namespace, keys)
Ledger->>CC: Query("queryTokens", tokenIDs)
CC->>State: GetState(tokenID)
State-->>CC: Token data
CC-->>Ledger: Token data array
Ledger-->>Net: Token data
Net-->>App: Token data
sequenceDiagram
participant App as Application
participant Net as Network Service
participant CC as Token Chaincode
participant State as World State
App->>Net: AreTokensSpent(tokenIDs)
Net->>CC: Query("areTokensSpent", tokenIDs)
CC->>State: GetState(spentKey)
State-->>CC: Spent markers
CC->>CC: Check each token
CC-->>Net: Boolean array
Net-->>App: [true, false, true, ...]
token:
enabled: true
tms:
my-fabric-tms:
network: fabric-network-name # Matches fsc.networks configuration
channel: my-channel
namespace: my-chaincode-id # Token chaincode name
token:
finality:
type: delivery # "delivery" or "notification"
committer:
maxRetries: 3
retryWaitDuration: 5s
delivery:
mapperParallelism: 10 # Parallel transaction mappers
blockProcessParallelism: 10 # Parallel block processors
lruSize: 30 # Cache size for recent transactions
listenerTimeout: 10s # Timeout for listener notifications
# Chaincode-based endorsement (default)
# No additional configuration needed - uses Fabric's endorsement policies
fabric.Network)
fabric.ledger)
endorsement.ChaincodeEndorsementService)
finality.ListenerManager)
tcc.TokenChaincode)
// Fabric uses SHA256(nonce || creator) for transaction IDs
func (n *Network) ComputeTxID(id *driver.TxID) string {
temp := &fabric.TxID{
Nonce: id.Nonce,
Creator: id.Creator,
}
return n.n.TransactionManager().ComputeTxID(temp)
}