I am trying to run a rewards example on .hyperledger 2.2. The contract is successfully packaged and deployed. I was also able to run the application successfully and enroll admin and user.
Chaincode successfully deployed :
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'
Enroll admin successfully :
Wallet path: ../fabric-samples/asset-transfer-basic/application-customerloyalty/wallet
Successfully enrolled admin user "admin" and imported it into the wallet
was able to successfully register user :
app running on port: 8000
Using param - firstname: Test lastname: User email: test@example.com 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: 'test@example.com',
phoneNumber: '111-111-1111',
points: 0
}
Get member state
memberResponse.parse_response:
{
accountNumber: '123456',
firstName: 'Test',
lastName: 'User',
email: 'test@example.com',
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: 'test@example.com',
phoneNumber: '111-111-1111',
points: 0
}
Wallet path: ../fabric-samples/asset-transfer-basic/application-customerloyalty/wallet
However, when I try to get transaction information in the app I get the following error with no response from peers :
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'
}
the above log indicates that json syntax is not correct in network.js file both invoking submitTransaction function. excerpt from Network.js file is :
/*
* 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.log(`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.log(`\nGet earn points transactions state for ${userType} ${userId}`);
//for debug only
console.log(await contract.submitTransaction('EarnPointsTransactionsInfo', 'userType', 'userId'));
//
let earnPointsTransactions = await contract.submitTransaction('EarnPointsTransactionsInfo', userType, userId);
//for debug only
console.log(await contract.submitTransaction('EarnPointsTransactionsInfo', userType, userId));
//
earnPointsTransactions = JSON.parse(earnPointsTransactions.toString());
console.log(earnPointsTransactions);
// Disconnect from the gateway.
await gateway2.disconnect();
return earnPointsTransactions;
}
catch(err) {
//print and return error
console.log(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.log(`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.log(`\nGet use points transactions state for ${userType} ${userId}`);
let usePointsTransactions = await contract.submitTransaction('UsePointsTransactionsInfo',userType, userId);
usePointsTransactions = JSON.parse(usePointsTransactions.toString());
console.log(usePointsTransactions);
// Disconnect from the gateway.
await gateway2.disconnect();
return usePointsTransactions;
}
I have tried to check logs from the peer using docker logs <container name> :
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
Here is the smart contract script 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;`
it seems that there is an syntax error with json.stringify. I don't know what to do next, or how to solve this. Any ideas?
I suspect that you have never invoked your instantiate transaction function and so the earnPointsTransactionsKey
ledger key contains no data:
% node --eval="JSON.parse(Buffer.from(''))"
SyntaxError: Unexpected end of JSON input
at JSON.parse (<anonymous>)
Rather than relying on an initialize transaction to set effectively empty initial state, you might consider a helper function in your smart contract, something like this:
async getEarnPointsTransactions(ctx) {
const data = await ctx.stub.getState(earnPointsTransactionsKey);
if (!data || data.length === 0) {
return [];
}
return JSON.parse(data);
}
Also consider that all of your transactions that update the ledger are modifying the value of the earnPointsTransactionsKey
ledger key. This is going to introduce contention as load increases and you are likely to experience MVCC_READ_CONFLICT failures as transactions concurrently update this state. These failures can be mitigated by implementing submit retry logic in your client application. You might consider different implementation approaches, such as: