@hlf-core/transport-common
This package contains exactly what must match on both sides — on the client and in the chaincode.
It depends neither on fabric-network nor on fabric-shim, and lives in both places as one and
the same code. In other words, it is the protocol itself, factored out separately so that it cannot
be accidentally implemented differently on the two sides.
The key idea of the whole transport is formulated right here: the interaction is built not on a set
of contract functions but on a single one. Any command is packed into an envelope and travels
through the single method transportFabricExecute (this and the neighboring constants are defined
in the package). What exactly was invoked is determined by the name field in the envelope. From
this follows an important consequence: adding a new command does not require reinstalling the
chaincode — it is enough to register a handler by name.
The base command class is TransportFabricCommandAsync<U, V> with the isReadonly flag. The
request itself travels in TransportFabricRequestPayload<U> — an envelope with the fields id,
name, request, options, isReadonly, and isNeedReply. The envelope has a parse method,
which on the chaincode side checks the function name and the number of parameters, deserializes the
data, restores the defaults, and validates them, and a clear method, which clears the default
values before sending. The latter is not optimization for optimization’s sake: everything that
travels in the envelope will be written to the ledger forever, so there must be nothing superfluous
there. A characteristic detail: the Ed25519 algorithm is considered the default and is not
transmitted over the network at all.
The response comes back in TransportFabricResponsePayload<V>, and here the result and the error
live in one response field. Thanks to this, a chaincode error reaches the client as an object with
a code and details, rather than as lost context.
The command options (TransportFabricCommandOptions) add the fields userId and signature to the
standard @ts-core options — that very application-level signature:
export interface ITransportFabricCommandOptions extends ITransportCommandOptions {
userId?: string;
signature?: ISignature;
}
The readonly command NonceGetCommand is responsible for a fresh nonce — the client takes the
current value, increments it, and signs the next command with it:
export class NonceGetCommand extends TransportFabricCommandAsync<string, string> {
public static readonly NAME = 'NonceGetCommand';
constructor(uid: UID) {
super(NonceGetCommand.NAME, getUid(uid), null, true); // the last argument is isReadonly
}
}
For more on signature verification, see the “Security” section.
The chaincode metadata is factored out here as well — ChaincodeMode, IChaincodeMetadata,
ChaincodeMetadataGetCommand — through which the client can, for example, find out whether a
contract has batch mode enabled and choose the appropriate transport.