Я пытаюсь запустить пример вознаграждения на .hyperledger 2.2. Контракт успешно упакован и развернут. Я также смог успешно запустить приложение и зарегистрировать администратора и пользователя.
Чейнкод успешно развернут:
Committed chaincode definition for chaincode 'customerloyalty' on channel 'mychannel':
Version: 1.0, Sequence: 1, Endorsement Plugin: escc, Validation Plugin: vscc, Approvals: [Org1MSP: true, Org2MSP: true]
Query chaincode definition successful on peer0.org2 on channel 'mychannel'
Зарегистрировать администратора успешно:
Wallet path: ../fabric-samples/asset-transfer-basic/application-customerloyalty/wallet
Successfully enrolled admin user "admin" and imported it into the wallet
удалось успешно зарегистрировать пользователя:
app running on port: 8000
Using param - firstname: Test lastname: User email: [email protected] phonenumber: 111-111-1111 accountNumber: 123456 cardId: 123
Valid Entries
Wallet path: ../fabric-samples/asset-transfer-basic/application-customerloyalty/wallet
Successfully registered and enrolled admin user 123 and imported it into the wallet
admin user admin disconnected
Submit Create Member transaction.
createMemberResponse:
{
accountNumber: '123456',
firstName: 'Test',
lastName: 'User',
email: '[email protected]',
phoneNumber: '111-111-1111',
points: 0
}
Get member state
memberResponse.parse_response:
{
accountNumber: '123456',
firstName: 'Test',
lastName: 'User',
email: '[email protected]',
phoneNumber: '111-111-1111',
points: 0
}
memberData using param - accountNumber: 123456 cardId: 123
Wallet path: ../fabric-samples/asset-transfer-basic/application-customerloyalty/wallet
Get member state
{
accountNumber: '123456',
firstName: 'Test',
lastName: 'User',
email: '[email protected]',
phoneNumber: '111-111-1111',
points: 0
}
Wallet path: ../fabric-samples/asset-transfer-basic/application-customerloyalty/wallet
Однако, когда я пытаюсь получить информацию о транзакции в приложении, я получаю следующую ошибку без ответа от одноранговых узлов:
Get use points transactions state for member 123456
2023-01-05T21:28:46.042Z - error: [Transaction]: Error: No valid responses from any peers. Errors:
peer=peer0.org1.example.com:7051, status=500, message=error in simulation: transaction returned with failure: SyntaxError: Unexpected end of JSON input
peer=peer0.org2.example.com:9051, status=500, message=error in simulation: transaction returned with failure: SyntaxError: Unexpected end of JSON input
at newEndorsementError (../fabric-samples/asset-transfer-basic/application-customerloyalty/node_modules/fabric-network/lib/transaction.js:74:12)
at getResponsePayload (/../fabric-samples/asset-transfer-basic/application-customerloyalty/node_modules/fabric-network/lib/transaction.js:41:23)
at Transaction.submit (../fabric-samples/asset-transfer-basic/application-customerloyalty/node_modules/fabric-network/lib/transaction.js:255:28)
at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
at async Object.usePointsTransactionsInfo (../fabric-samples/asset-transfer-basic/application-customerloyalty/network/network.js:592:41)
Error: No valid responses from any peers. Errors:
peer=peer0.org1.example.com:7051, status=500, message=error in simulation: transaction returned with failure: SyntaxError: Unexpected end of JSON input
peer=peer0.org2.example.com:9051, status=500, message=error in simulation: transaction returned with failure: SyntaxError: Unexpected end of JSON input
at newEndorsementError (../fabric-samples/asset-transfer-basic/application-customerloyalty/node_modules/fabric-network/lib/transaction.js:74:12)
at getResponsePayload (../fabric-samples/asset-transfer-basic/application-customerloyalty/node_modules/fabric-network/lib/transaction.js:41:23)
at Transaction.submit (../fabric-samples/asset-transfer-basic/application-customerloyalty/node_modules/fabric-network/lib/transaction.js:255:28)
at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
at async Object.usePointsTransactionsInfo (../fabric-samples/asset-transfer-basic/application-customerloyalty/network/network.js:592:41) {
responses: [
{
version: 0,
timestamp: null,
response: [Object],
payload: <Buffer >,
endorsement: null,
connection: [Object],
peer: 'peer0.org1.example.com:7051'
},
{
version: 0,
timestamp: null,
response: [Object],
payload: <Buffer >,
endorsement: null,
connection: [Object],
peer: 'peer0.org2.example.com:9051'
}
],
errors: []
}
Wallet path: ../fabric-samples/asset-transfer-basic/application-customerloyalty/wallet
Get earn points transactions state for member 123456
2023-01-05T21:28:46.192Z - error: [Transaction]: Error: No valid responses from any peers. Errors:
peer=peer0.org1.example.com:7051, status=500, message=error in simulation: transaction returned with failure: SyntaxError: Unexpected end of JSON input
peer=peer0.org2.example.com:9051, status=500, message=error in simulation: transaction returned with failure: SyntaxError: Unexpected end of JSON input
at newEndorsementError (../fabric-samples/asset-transfer-basic/application-customerloyalty/node_modules/fabric-network/lib/transaction.js:74:12)
at getResponsePayload (../fabric-samples/asset-transfer-basic/application-customerloyalty/node_modules/fabric-network/lib/transaction.js:41:23)
at Transaction.submit (../fabric-samples/asset-transfer-basic/application-customerloyalty/node_modules/fabric-network/lib/transaction.js:255:28)
at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
at async Object.earnPointsTransactionsInfo (../fabric-samples/asset-transfer-basic/application-customerloyalty/network/network.js:545:25)
Error: No valid responses from any peers. Errors:
peer=peer0.org1.example.com:7051, status=500, message=error in simulation: transaction returned with failure: SyntaxError: Unexpected end of JSON input
peer=peer0.org2.example.com:9051, status=500, message=error in simulation: transaction returned with failure: SyntaxError: Unexpected end of JSON input
at newEndorsementError (../fabric-samples/asset-transfer-basic/application-customerloyalty/node_modules/fabric-network/lib/transaction.js:74:12)
at getResponsePayload (../fabric-samples/asset-transfer-basic/application-customerloyalty/node_modules/fabric-network/lib/transaction.js:41:23)
at Transaction.submit (../fabric-samples/asset-transfer-basic/application-customerloyalty/node_modules/fabric-network/lib/transaction.js:255:28)
at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
at async Object.earnPointsTransactionsInfo (../fabric-samples/asset-transfer-basic/application-customerloyalty/network/network.js:545:25) {
responses: [
{
version: 0,
timestamp: null,
response: [Object],
payload: <Buffer >,
endorsement: null,
connection: [Object],
peer: 'peer0.org1.example.com:7051'
},
{
version: 0,
timestamp: null,
response: [Object],
payload: <Buffer >,
endorsement: null,
connection: [Object],
peer: 'peer0.org2.example.com:9051'
}
],
errors: []
}
node:internal/errors:484
ErrorCaptureStackTrace(err);
^
Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
at new NodeError (node:internal/errors:393:5)
at ServerResponse.setHeader (node:_http_outgoing:644:11)
at ServerResponse.header (../fabric-samples/asset-transfer-basic/application-customerloyalty/node_modules/express/lib/response.js:794:10)
at ServerResponse.send (../fabric-samples/asset-transfer-basic/application-customerloyalty/node_modules/express/lib/response.js:174:12)
at ServerResponse.json (../fabric-samples/asset-transfer-basic/application-customerloyalty/node_modules/express/lib/response.js:278:15)
at ../fabric-samples/asset-transfer-basic/application-customerloyalty/app.js:278:37
at process.processTicksAndRejections (node:internal/process/task_queues:95:5) {
code: 'ERR_HTTP_HEADERS_SENT'
}
приведенный выше журнал указывает, что синтаксис json неверен в файле network.js, который вызывает функцию submitTransaction. выдержка из файла Network.js:
/*
* Get all EarnPoints transactions data
* @param {String} cardId Card id to connect to network
*/
earnPointsTransactionsInfo: async function (cardId, userType, userId) {
// Create a new file system based wallet for managing identities.
const walletPath = path.join(process.cwd(), '/wallet');
const wallet = await Wallets.newFileSystemWallet(walletPath);
console.info(`Wallet path: ${walletPath}`);
try {
// Create a new gateway for connecting to our peer node.
const gateway2 = new Gateway();
await gateway2.connect(ccp, { wallet, identity: cardId, discovery: gatewayDiscovery });
// Get the network (channel) our contract is deployed to.
const network = await gateway2.getNetwork('mychannel');
// Get the contract from the network.
const contract = network.getContract('customerloyalty');
console.info(`\nGet earn points transactions state for ${userType} ${userId}`);
//for debug only
console.info(await contract.submitTransaction('EarnPointsTransactionsInfo', 'userType', 'userId'));
//
let earnPointsTransactions = await contract.submitTransaction('EarnPointsTransactionsInfo', userType, userId);
//for debug only
console.info(await contract.submitTransaction('EarnPointsTransactionsInfo', userType, userId));
//
earnPointsTransactions = JSON.parse(earnPointsTransactions.toString());
console.info(earnPointsTransactions);
// Disconnect from the gateway.
await gateway2.disconnect();
return earnPointsTransactions;
}
catch(err) {
//print and return error
console.info(err);
let error = {};
error.error = err.message;
return error;
}
},
usePointsTransactionsInfo: async function (cardId, userType, userId) {
// Create a new file system based wallet for managing identities.
const walletPath = path.join(process.cwd(), '/wallet');
const wallet = await Wallets.newFileSystemWallet(walletPath);
console.info(`Wallet path: ${walletPath}`);
try {
// Create a new gateway for connecting to our peer node.
const gateway2 = new Gateway();
await gateway2.connect(ccp, { wallet, identity: cardId, discovery: gatewayDiscovery });
// Get the network (channel) our contract is deployed to.
const network = await gateway2.getNetwork('mychannel');
// Get the contract from the network.
const contract = network.getContract('customerloyalty');
console.info(`\nGet use points transactions state for ${userType} ${userId}`);
let usePointsTransactions = await contract.submitTransaction('UsePointsTransactionsInfo',userType, userId);
usePointsTransactions = JSON.parse(usePointsTransactions.toString());
console.info(usePointsTransactions);
// Disconnect from the gateway.
await gateway2.disconnect();
return usePointsTransactions;
}
Я попытался проверить журналы от однорангового узла, используя журналы докеров <имя контейнера>:
2023-01-05 22:28:46 2023-01-05T21:28:46.023Z error [c-api:contracts-spi/chaincodefromcontract.js] [mychannel-fedc897c] SyntaxError: Unexpected end of JSON input
2023-01-05 22:28:46 2023-01-05T21:28:46.033Z error [c-api:lib/handler.js] [mychannel-fedc897c] Calling chaincode Invoke() returned error response [SyntaxError: Unexpected end of JSON input
2023-01-05 22:28:46 at JSON.parse (<anonymous>)
2023-01-05 22:28:46 at CustomerLoyalty.UsePointsTransactionsInfo (/usr/local/src/lib/customerloyalty.js:110:29)
2023-01-05 22:28:46 at processTicksAndRejections (node:internal/process/task_queues:96:5)
2023-01-05 22:28:46 at async ChaincodeFromContract.invokeFunctionality (/usr/local/src/node_modules/fabric-shim/lib/contract-spi/chaincodefromcontract.js:378:32)
2023-01-05 22:28:46 at async handleMessage (/usr/local/src/node_modules/fabric-shim/lib/handler.js:602:24)]. Sending ERROR message back to peer
2023-01-05 22:28:46 2023-01-05T21:28:46.181Z error [c-api:contracts-spi/chaincodefromcontract.js] [mychannel-644303c3] SyntaxError: Unexpected end of JSON input
2023-01-05 22:28:46 2023-01-05T21:28:46.184Z error [c-api:lib/handler.js] [mychannel-644303c3] Calling chaincode Invoke() returned error response [SyntaxError: Unexpected end of JSON input
2023-01-05 22:28:46 at JSON.parse (<anonymous>)
2023-01-05 22:28:46 at CustomerLoyalty.EarnPointsTransactionsInfo (/usr/local/src/lib/customerloyalty.js:89:29)
2023-01-05 22:28:46 at processTicksAndRejections (node:internal/process/task_queues:96:5)
2023-01-05 22:28:46 at async ChaincodeFromContract.invokeFunctionality (/usr/local/src/node_modules/fabric-shim/lib/contract-spi/chaincodefromcontract.js:378:32)
2023-01-05 22:28:46 at async handleMessage (/usr/local/src/node_modules/fabric-shim/lib/handler.js:602:24)]. Sending ERROR message back to peer
2023-01-05 22:32:51 2023-01-05T21:32:51.616Z info [c-api:lib/handler.js] [mychannel-68bdfcd2] Calling chaincode Invoke() succeeded. Sending COMPLETED message back to peer
2023-01-05 22:32:53 2023-01-05T21:32:53.977Z error [c-api:contracts-spi/chaincodefromcontract.js] [mychannel-7f185a49] SyntaxError: Unexpected end of JSON input
2023-01-05 22:32:53 2023-01-05T21:32:53.989Z error [c-api:lib/handler.js] [mychannel-7f185a49] Calling chaincode Invoke() returned error response [SyntaxError: Unexpected end of JSON input
2023-01-05 22:32:53 at JSON.parse (<anonymous>)
2023-01-05 22:32:53 at CustomerLoyalty.UsePointsTransactionsInfo (/usr/local/src/lib/customerloyalty.js:110:29)
2023-01-05 22:32:53 at processTicksAndRejections (node:internal/process/task_queues:96:5)
2023-01-05 22:32:53 at async ChaincodeFromContract.invokeFunctionality (/usr/local/src/node_modules/fabric-shim/lib/contract-spi/chaincodefromcontract.js:378:32)
2023-01-05 22:32:53 at async handleMessage (/usr/local/src/node_modules/fabric-shim/lib/handler.js:602:24)]. Sending ERROR message back to peer
2023-01-05 22:32:54 2023-01-05T21:32:54.195Z error [c-api:contracts-spi/chaincodefromcontract.js] [mychannel-44d04ba9] SyntaxError: Unexpected end of JSON input
2023-01-05 22:32:54 2023-01-05T21:32:54.197Z error [c-api:lib/handler.js] [mychannel-44d04ba9] Calling chaincode Invoke() returned error response [SyntaxError: Unexpected end of JSON input
2023-01-05 22:32:54 at JSON.parse (<anonymous>)
2023-01-05 22:32:54 at CustomerLoyalty.EarnPointsTransactionsInfo (/usr/local/src/lib/customerloyalty.js:89:29)
2023-01-05 22:32:54 at processTicksAndRejections (node:internal/process/task_queues:96:5)
2023-01-05 22:32:54 at async ChaincodeFromContract.invokeFunctionality (/usr/local/src/node_modules/fabric-shim/lib/contract-spi/chaincodefromcontract.js:378:32)
2023-01-05 22:32:54 at async handleMessage (/usr/local/src/node_modules/fabric-shim/lib/handler.js:602:24)]. Sending ERROR message back to peer
Вот скрипт смарт-контракта customerloyalty.js:
'use strict';
const { Contract } = require('fabric-contract-api'); const allPartnersKey = 'all-partners'; const earnPointsTransactionsKey = 'earn-points-transactions'; const usePointsTransactionsKey = 'use-points-transactions';
class CustomerLoyalty extends Contract {
// Init function executed when the ledger is instantiated
async instantiate(ctx) {
console.info('============= START : Initialize Ledger ===========');
await ctx.stub.putState('instantiate', Buffer.from('INIT-LEDGER'));
await ctx.stub.putState(allPartnersKey, Buffer.from(JSON.stringify([])));
await ctx.stub.putState(earnPointsTransactionsKey, Buffer.from(JSON.stringify([])));
await ctx.stub.putState(usePointsTransactionsKey, Buffer.from(JSON.stringify([])));
console.info('============= END : Initialize Ledger ===========');
}
// Add a member on the ledger
async CreateMember(ctx, member) {
member = JSON.parse(member);
await ctx.stub.putState(member.accountNumber, Buffer.from(JSON.stringify(member)));
return JSON.stringify(member);
}
// Add a partner on the ledger, and add it to the all-partners list
async CreatePartner(ctx, partner) {
partner = JSON.parse(partner);
await ctx.stub.putState(partner.id, Buffer.from(JSON.stringify(partner)));
let allPartners = await ctx.stub.getState(allPartnersKey);
allPartners = JSON.parse(allPartners);
allPartners.push(partner);
await ctx.stub.putState(allPartnersKey, Buffer.from(JSON.stringify(allPartners)));
return JSON.stringify(partner);
}
// Record a transaction where a member earns points
async EarnPoints(ctx, earnPoints) {
earnPoints = JSON.parse(earnPoints);
earnPoints.timestamp = new Date((ctx.stub.txTimestamp.seconds.low*1000)).toGMTString();
earnPoints.transactionId = ctx.stub.txId;
let member = await ctx.stub.getState(earnPoints.member);
member = JSON.parse(member);
member.points += earnPoints.points;
await ctx.stub.putState(earnPoints.member, Buffer.from(JSON.stringify(member)));
let earnPointsTransactions = await ctx.stub.getState(earnPointsTransactionsKey);
earnPointsTransactions = JSON.parse(earnPointsTransactions);
earnPointsTransactions.push(earnPoints);
await ctx.stub.putState(earnPointsTransactionsKey, Buffer.from(JSON.stringify(earnPointsTransactions)));
return JSON.stringify(earnPoints);
}
// Record a transaction where a member redeems points
async UsePoints(ctx, usePoints) {
usePoints = JSON.parse(usePoints);
usePoints.timestamp = new Date((ctx.stub.txTimestamp.seconds.low*1000)).toGMTString();
usePoints.transactionId = ctx.stub.txId;
let member = await ctx.stub.getState(usePoints.member);
member = JSON.parse(member);
if (member.points < usePoints.points) {
throw new Error('Member does not have sufficient points');
}
member.points -= usePoints.points;
await ctx.stub.putState(usePoints.member, Buffer.from(JSON.stringify(member)));
let usePointsTransactions = await ctx.stub.getState(usePointsTransactionsKey);
usePointsTransactions = JSON.parse(usePointsTransactions);
usePointsTransactions.push(usePoints);
await ctx.stub.putState(usePointsTransactionsKey, Buffer.from(JSON.stringify(usePointsTransactions)));
return JSON.stringify(usePoints);
}
// Get earn points transactions of the particular member or partner
async EarnPointsTransactionsInfo(ctx, userType, userId) {
let transactions = await ctx.stub.getState(earnPointsTransactionsKey);
transactions = JSON.parse(transactions);
let userTransactions = [];
for (let transaction of transactions) {
if (userType === 'member') {
if (transaction.member === userId) {
userTransactions.push(transaction);
}
} else if (userType === 'partner') {
if (transaction.partner === userId) {
userTransactions.push(transaction);
}
}
}
return JSON.stringify(userTransactions);
}
// Get use points transactions of the particular member or partner
async UsePointsTransactionsInfo(ctx, userType, userId) {
let transactions = await ctx.stub.getState(usePointsTransactionsKey);
transactions = JSON.parse(transactions);
let userTransactions = [];
for (let transaction of transactions) {
if (userType === 'member') {
if (transaction.member === userId) {
userTransactions.push(transaction);
}
} else if (userType === 'partner') {
if (transaction.partner === userId) {
userTransactions.push(transaction);
}
}
}
return JSON.stringify(userTransactions);
}
// get the state from key
async GetState(ctx, key) {
let data = await ctx.stub.getState(key);
let jsonData = JSON.parse(data.toString());
return JSON.stringify(jsonData);
}
module.exports = CustomerLoyalty;`
кажется, что есть синтаксическая ошибка с json.stringify. Я не знаю, что делать дальше, или как решить эту проблему. Есть идеи?
Я подозреваю, что вы никогда не вызывали функцию создания экземпляра транзакции, поэтому ключ реестра earnPointsTransactionsKey
не содержит данных:
% node --eval = "JSON.parse(Buffer.from(''))"
SyntaxError: Unexpected end of JSON input
at JSON.parse (<anonymous>)
Вместо того, чтобы полагаться на транзакцию инициализации для установки фактически пустого начального состояния, вы можете рассмотреть вспомогательную функцию в своем смарт-контракте, что-то вроде этого:
async getEarnPointsTransactions(ctx) {
const data = await ctx.stub.getState(earnPointsTransactionsKey);
if (!data || data.length === 0) {
return [];
}
return JSON.parse(data);
}
Также учтите, что все ваши транзакции, которые обновляют реестр, изменяют значение ключа реестра earnPointsTransactionsKey
. Это вызовет конкуренцию по мере увеличения нагрузки, и вы, вероятно, столкнетесь с ошибками MVCC_READ_CONFLICT, поскольку транзакции одновременно обновляют это состояние. Эти сбои можно смягчить, внедрив в клиентское приложение логику повторных попыток отправки. Вы можете рассмотреть различные подходы к реализации, такие как:
Это сообщение об ошибке указывает на то, что заголовки ответа HTTP уже отправлены клиенту и не могут быть изменены. Обычно это происходит, когда ответ уже отправлен клиенту и предпринимается попытка отправить другой ответ. Конкретное место в коде, где возникает эта ошибка, находится в «ServerResponse.header» в файле «response.js» в библиотеке «express», а конкретная функция, вызывающая проблему, — «register» в «UserController». .js" в строке 60.