Каждый узел имеет свой собственный контейнер с цепочечным кодом для каждой версии заданного кода цепочечного кода.
Когда цепной код установлен на одноранговом узле, пакет кода кода цепного кода записывается в файловую систему.
Позже, когда одноранговый узел получает запрос на вызов функции в коде цепи (Init () или Invoke (), когда Init () запускается при создании экземпляра), узел проверяет, запущен ли уже код цепи, и если нет, то это:
- Раскручивает контейнер для компиляции пакета кода с цепочкой кодов, чтобы создать двоичный файл с кодом цепочки кодов, а затем уничтожает его
- Вращает контейнер, который на самом деле запускает бинарный файл с цепным кодом.
Бинарный код цепного кода:
- Подключается к узлу через gRPC и регистрируется в качестве имени, с которым он установлен.
- Запускает бесконечный цикл, в котором он ожидает команды для имитации транзакций от партнера.
Когда партнер получает предложение от клиента, он:
- Находит поток gRPC контейнера с цепочечным кодом и пересылает предложение от клиента в цепочечный код
- Подготавливает карту чтения и записи ключа, что прокладка цепного кода будет запрашивать одноранговый узел во время его выполнения, который называется Набор для чтения-записи .
Затем прокладка цепного кода, работающая внутри контейнера, извлекает аргументы из предложения и запускает логику цепного кода (часть его двоичного файла).
Если логика цепочечного кода содержит такие операции доступа к данным, как GetState или PutState, она отправляет запрос одноранговому узлу в тот же поток gRPC, к которому он подключен, а затем одноранговый узел выполняет следующие действия:
- Если операция с данными является операцией чтения, она добавляет к набору чтения-записи ключ и версию, считанную из ключа, и отправляет обратно ключ и значение в контейнер-прокладку цепного кода через поток gRPC.
- Если операция с данными является операцией записи, она добавляет к набору для чтения-записи ключ, значение и версию, а затем отправляет обратно «OK» в прокладку кода цепи (*).
(*) Лично я считаю, что этот шаг не нужен ... он просто продлевает время выполнения
После того, как цепная кодовая цепочка закончила вычислять транзакцию, она отправляет результат (т. Е. «ОК») партнеру вместе с маркером, который обозначает, что транзакция завершила выполнение.
Поскольку записанные значения на самом деле не записываются в БД, а просто добавляются в карту в памяти, это называется «симуляцией транзакций».
Затем одноранговый узел переходит к подписанию результатов моделирования транзакции (карты набора для чтения-записи и результата из цепочки кодов цепей) и затем возвращает подписанное моделирование транзакции (также называемое «подтверждением») обратно клиенту в качестве ответа.
In that case, I'd like to ask you how those endorsing peers can execute or access the chaincode container in parallel?
Вы можете сделать это параллельно, потому что, когда цепочка кода запускает транзакцию, она делает это для отдельной программы .