@hlf-core/transport-common
Этот пакет содержит ровно то, что обязано совпадать у обеих сторон — у клиента и у chaincode.
Он не зависит ни от fabric-network, ни от fabric-shim, и живёт и там, и там одним и тем же
кодом. Иными словами, это сам протокол, вынесенный отдельно, чтобы его нельзя было случайно
реализовать на двух сторонах по-разному.
Ключевая идея всего транспорта формулируется именно здесь: взаимодействие построено не на наборе
функций контракта, а на одной. Любая команда упаковывается в конверт и идёт через единственный
метод transportFabricExecute (эта и соседние константы заданы в пакете). Что именно вызвано —
определяет поле name в конверте. Отсюда важное следствие: добавление новой команды не требует
переустановки chaincode, достаточно зарегистрировать обработчик по имени.
Базовый класс команды — TransportFabricCommandAsync<U, V> с флагом isReadonly. Сам запрос едет
в TransportFabricRequestPayload<U> — конверте с полями id, name, request, options,
isReadonly и isNeedReply. У конверта есть метод parse, который на стороне chaincode проверяет
имя функции и число параметров, десериализует данные, восстанавливает умолчания и валидирует их,
и метод clear, который перед отправкой очищает значения по умолчанию. Последнее — не
оптимизация ради оптимизации: всё, что уедет в конверте, ляжет в ledger навсегда, поэтому лишнего
там быть не должно. Характерная деталь: алгоритм Ed25519 считается умолчанием и по сети не
передаётся вовсе.
Ответ возвращается в TransportFabricResponsePayload<V>, и здесь результат и ошибка живут в одном
поле response. Благодаря этому ошибка chaincode доходит до клиента как объект с кодом и деталями,
а не как потерянный контекст.
Опции команды (TransportFabricCommandOptions) добавляют к стандартным опциям @ts-core поля
userId и signature — ту самую подпись на уровне приложения:
export interface ITransportFabricCommandOptions extends ITransportCommandOptions {
userId?: string;
signature?: ISignature;
}
За свежий nonce отвечает readonly-команда NonceGetCommand — клиент берёт текущее значение,
увеличивает и подписывает им следующую команду:
export class NonceGetCommand extends TransportFabricCommandAsync<string, string> {
public static readonly NAME = 'NonceGetCommand';
constructor(uid: UID) {
super(NonceGetCommand.NAME, getUid(uid), null, true); // последний аргумент — isReadonly
}
}
Подробнее о проверке подписи — в разделе «Безопасность».
Сюда же вынесены метаданные chaincode — ChaincodeMode, IChaincodeMetadata, ChaincodeMetadataGetCommand,
по которым клиент может, например, узнать, включён ли у контракта batch-режим, и выбрать нужный
транспорт.