From 8dc6bc020225dedc0434cb27de877d814bdfb3d6 Mon Sep 17 00:00:00 2001 From: wenjian3 Date: Wed, 20 Mar 2019 12:05:41 -0400 Subject: [PATCH] [FABN-1183] Update quantity to be decimal string Change-Id: I2c17b1eb0439d3f27318f954a7d090ca902e9db1 Signed-off-by: Wenjian Qiao --- fabric-client/lib/token-utils.js | 4 +++- fabric-client/test/BlockDecoder.js | 12 +++++------ fabric-client/test/TokenClient.js | 5 ++--- fabric-client/test/token-utils.js | 30 +++++++++++++++++++++------- test/integration/token.js | 32 +++++++++++++++++------------- 5 files changed, 52 insertions(+), 31 deletions(-) diff --git a/fabric-client/lib/token-utils.js b/fabric-client/lib/token-utils.js index 8bf46e18e8..c042577155 100644 --- a/fabric-client/lib/token-utils.js +++ b/fabric-client/lib/token-utils.js @@ -177,7 +177,9 @@ module.exports.buildTokenCommandHeader = (creator, channelId, nonce, tlsCertHash header.setCreator(creator.serialize()); header.setNonce(nonce); header.setTimestamp(timestamp); - header.setTlsCertHash(tlsCertHash); + if (tlsCertHash !== undefined && tlsCertHash !== null) { + header.setTlsCertHash(tlsCertHash); + } return header; }; diff --git a/fabric-client/test/BlockDecoder.js b/fabric-client/test/BlockDecoder.js index aa74bd827f..895e39c725 100644 --- a/fabric-client/test/BlockDecoder.js +++ b/fabric-client/test/BlockDecoder.js @@ -496,8 +496,8 @@ describe('BlockDecoder', () => { }); it('should add action to data when transaction with issue action is given', () => { - const output1 = {owner: {type: 0, raw: Buffer.from('owner1')}, type: 'type1', quantity: '0x3c'}; - const output2 = {owner: {type: 0, raw: Buffer.from('owner2')}, type: 'type2', quantity: '0x5d'}; + const output1 = {owner: {type: 0, raw: Buffer.from('owner1')}, type: 'type1', quantity: '100'}; + const output2 = {owner: {type: 0, raw: Buffer.from('owner2')}, type: 'type2', quantity: '200'}; // build a token transaction protobuf message const issue = new fabprotos.token.Issue(); @@ -515,8 +515,8 @@ describe('BlockDecoder', () => { }); it('should add action to data when transaction with transfer action is given', () => { - const output1 = {owner: {type: 0, raw: Buffer.from('owner1')}, type: 'type1', quantity: '0x3c'}; - const output2 = {owner: {type: 0, raw: Buffer.from('owner2')}, type: 'type2', quantity: '0x5d'}; + const output1 = {owner: {type: 0, raw: Buffer.from('owner1')}, type: 'type1', quantity: '100'}; + const output2 = {owner: {type: 0, raw: Buffer.from('owner2')}, type: 'type2', quantity: '200'}; const tokenId = {index: 0, tx_id: 'input_txid'}; // build a token transaction protobuf message @@ -536,8 +536,8 @@ describe('BlockDecoder', () => { }); it('should add action to data when transaction with redeem action is given', () => { - const output1 = {type: 'type1', quantity: '0x3c'}; - const output2 = {owner: {type: 0, raw: Buffer.from('owner2')}, type: 'type2', quantity: '0x5d'}; + const output1 = {type: 'type1', quantity: '100'}; + const output2 = {owner: {type: 0, raw: Buffer.from('owner2')}, type: 'type2', quantity: '200'}; const tokenId = {index: 0, tx_id: 'input_txid'}; // build a token transaction protobuf message diff --git a/fabric-client/test/TokenClient.js b/fabric-client/test/TokenClient.js index 025b22b9eb..1d6bd1efd1 100644 --- a/fabric-client/test/TokenClient.js +++ b/fabric-client/test/TokenClient.js @@ -20,7 +20,6 @@ const Client = require('../lib/Client'); const {Identity} = require('fabric-common'); const TokenClient = rewire('../lib/TokenClient'); const TransactionID = require('../lib/TransactionID.js'); -const token_utils = require('../lib/token-utils.js'); const fabprotos = require('fabric-protos'); const sinon = require('sinon'); @@ -443,8 +442,8 @@ describe('TokenClient', () => { // prepare mockResponse for sendTokenComandStub const tokenId1 = {tx_id: 'mock_tx_id1', index: 0}; const tokenId2 = {tx_id: 'mock_tx_id2', index: 0}; - const token1 = {id: tokenId1, type: 'abc123', quantity: token_utils.toHex(100)}; - const token2 = {id: tokenId2, type: 'xyz', quantity: token_utils.toHex(200)}; + const token1 = {id: tokenId1, type: 'abc123', quantity: '100'}; + const token2 = {id: tokenId2, type: 'xyz', quantity: '200'}; mockTokens = [token1, token2]; mockResponse = new fabprotos.token.CommandResponse(); mockResponse.setUnspentTokens({tokens: mockTokens}); diff --git a/fabric-client/test/token-utils.js b/fabric-client/test/token-utils.js index b814575f7f..6cbd88687e 100644 --- a/fabric-client/test/token-utils.js +++ b/fabric-client/test/token-utils.js @@ -48,7 +48,7 @@ describe('token-utils', () => { beforeEach(() => { // prepare token request const owner = {type: fabprotos.token.TokenOwner_MSP_IDENTIFIER, raw: Buffer.from('test-owner')}; - param = {owner: owner, type: 'abc123', quantity: TokenUtils.toHex(210)}; + param = {owner: owner, type: 'abc123', quantity: '210'}; request = {params: [param], txId: txId, tokenIds: tokenIds}; }); @@ -241,8 +241,8 @@ describe('token-utils', () => { // prepare token request for issue const owner1 = {type: fabprotos.token.TokenOwner_MSP_IDENTIFIER, raw: Buffer.from('owner1')}; const owner2 = {type: fabprotos.token.TokenOwner_MSP_IDENTIFIER, raw: Buffer.from('owner2')}; - param1 = {owner: owner1, type: 'abc123', quantity: TokenUtils.toHex(210)}; - param2 = {owner: owner2, type: 'horizon', quantity: TokenUtils.toHex(300)}; + param1 = {owner: owner1, type: 'abc123', quantity: '210'}; + param2 = {owner: owner2, type: 'horizon', quantity: '300'}; request = { params: [param1, param2], txId: txId, @@ -267,8 +267,8 @@ describe('token-utils', () => { const tokenId = {tx_id: 'mock_tx_id', index: 0}; const owner1 = {type: fabprotos.token.TokenOwner_MSP_IDENTIFIER, raw: Buffer.from('owner1')}; const owner2 = {type: fabprotos.token.TokenOwner_MSP_IDENTIFIER, raw: Buffer.from('owner2')}; - param1 = {owner: owner1, quantity: TokenUtils.toHex(100)}; - param2 = {owner: owner2, quantity: TokenUtils.toHex(200)}; + param1 = {owner: owner1, quantity: '100'}; + param2 = {owner: owner2, quantity: '200'}; request = { tokenIds: [tokenId], @@ -296,7 +296,7 @@ describe('token-utils', () => { beforeEach(() => { // prepare token request for redeem const tokenId = {tx_id: 'mock_tx_id', index: 0}; - param1 = {quantity: TokenUtils.toHex(100)}; + param1 = {quantity: '100'}; request = { tokenIds: [tokenId], params: param1, @@ -541,7 +541,7 @@ describe('token-utils', () => { mockCreator = {serialize: serializeStub}; }); - it('should return a token command header', () => { + it('should return a token command header with tls cert', () => { const expectedHeader = new fabprotos.token.Header(); expectedHeader.setChannelId(channelId); expectedHeader.setCreator(Buffer.from('serialized-creator')); @@ -558,6 +558,22 @@ describe('token-utils', () => { header.toBuffer().should.deep.equal(expectedHeader.toBuffer()); }); + it('should return a token command header without tls cert', () => { + const expectedHeader = new fabprotos.token.Header(); + expectedHeader.setChannelId(channelId); + expectedHeader.setCreator(Buffer.from('serialized-creator')); + expectedHeader.setNonce(nonce); + + const header = TokenUtils.buildTokenCommandHeader(mockCreator, channelId, nonce); + + // verify header has timestamp + header.hasOwnProperty('timestamp').should.equal(true); + expectedHeader.timestamp = header.timestamp; + + // compare toBuffer since they are protobuf messages + header.toBuffer().should.deep.equal(expectedHeader.toBuffer()); + }); + it('should get error when creator serialize throws error', () => { (() => { const fakeError = new Error('forced build header error'); diff --git a/test/integration/token.js b/test/integration/token.js index 841359f839..fa2c30f01b 100644 --- a/test/integration/token.js +++ b/test/integration/token.js @@ -93,12 +93,12 @@ test('\n\n***** Token end-to-end flow (green path): issue, transfer, redeem and let param = { owner: {type: 0, raw: user1Identity.serialize()}, type: 'abc123', - quantity: tokenUtils.toHex(200), + quantity: '200' }; const param2 = { owner: {type: 0, raw: user1Identity.serialize()}, type: 'horizon', - quantity: tokenUtils.toHex(200), + quantity: '200' }; let request = { params: [param, param2], @@ -162,7 +162,7 @@ test('\n\n***** Token end-to-end flow (green path): issue, transfer, redeem and // build requst for user1 to redeem token txId = user1TokenClient.getClient().newTransactionID(); param = { - quantity: tokenUtils.toHex(50), + quantity: '50' }; request = { tokenIds: [redeemToken.id], @@ -179,7 +179,7 @@ test('\n\n***** Token end-to-end flow (green path): issue, transfer, redeem and // verify owner's (user1) unspent tokens after redeem - pass optional request request = {txId: user1TokenClient.getClient().newTransactionID()}; result = await user1TokenClient.list(request); - const remainingQuantity = tokenUtils.toHex(200 - 50); + const remainingQuantity = '150'; // 200 - 50 logger.debug('(org1)list tokens after transfer token %s', util.inspect(result, false, null)); t.equals(result.length, 1, 'Checking number of tokens for user1 after redeem'); t.equals(result[0].type, redeemToken.type, 'Checking token type for user1 after redeem'); @@ -216,7 +216,7 @@ test('\n\n***** Token end-to-end flow: double spending fails *****\n\n', async ( let param = { owner: {type: fabprotos.token.TokenOwner_MSP_IDENTIFIER, raw: user1Identity.serialize()}, type: 'abc123', - quantity: tokenUtils.toHex(210) + quantity: '210' }; let request = { params: [param], @@ -306,7 +306,7 @@ test('\n\n***** Token end-to-end flow: non owner transfer fails *****\n\n', asyn let param = { owner: {type: fabprotos.token.TokenOwner_MSP_IDENTIFIER, raw: user1Identity.serialize()}, type: 'abc123', - quantity: tokenUtils.toHex(210) + quantity: '210' }; let request = { params: [param], @@ -330,7 +330,7 @@ test('\n\n***** Token end-to-end flow: non owner transfer fails *****\n\n', asyn txId = user2TokenClient.getClient().newTransactionID(); param = { owner: {type: fabprotos.token.TokenOwner_MSP_IDENTIFIER, raw: user2Identity.serialize()}, - quantity: tokenUtils.toHex(10) + quantity: '10' }; request = { tokenIds: [transferToken.id], @@ -375,7 +375,7 @@ test('\n\n***** Token end-to-end flow: invalid transfer amount fails *****\n\n', let param = { owner: {type: fabprotos.token.TokenOwner_MSP_IDENTIFIER, raw: user1Identity.serialize()}, type: 'abc123', - quantity: tokenUtils.toHex(210) + quantity: '210' }; let request = { params: [param], @@ -399,7 +399,7 @@ test('\n\n***** Token end-to-end flow: invalid transfer amount fails *****\n\n', txId = user1TokenClient.getClient().newTransactionID(); param = { owner: {type: fabprotos.token.TokenOwner_MSP_IDENTIFIER, raw: user2Identity.serialize()}, - quantity: tokenUtils.toHex(10) + quantity: '10' }; request = { tokenIds: [transferToken.id], @@ -442,7 +442,7 @@ test('\n\n***** Token end-to-end flow: invalid redeem amount fails *****\n\n', a let param = { owner: {type: fabprotos.token.TokenOwner_MSP_IDENTIFIER, raw: user1Identity.serialize()}, type: 'abc123', - quantity: tokenUtils.toHex(100) + quantity: '100' }; let request = { params: [param], @@ -465,7 +465,7 @@ test('\n\n***** Token end-to-end flow: invalid redeem amount fails *****\n\n', a // build request for user1 to transfer transfer token to user2 txId = user1TokenClient.getClient().newTransactionID(); param = { - quantity: tokenUtils.toHex(110) + quantity: '110' }; request = { tokenIds: [redeemToken.id], @@ -481,7 +481,7 @@ test('\n\n***** Token end-to-end flow: invalid redeem amount fails *****\n\n', a } catch (err) { t.equals( err.message, - 'command response has error: total quantity [100] from TokenIds is less than quantity [0x6e] to be redeemed', + 'command response has error: total quantity [100] from TokenIds is less than quantity [110] to be redeemed', 'Redeem failed as expected because redeemed quantity exceeded token quantity' ); t.end(); @@ -546,10 +546,14 @@ function validateTransactionEnvelope(txEnvelope, commandName, expectedInputs, ex logger.debug('queried transaction is: \n%s', util.inspect(txEnvelope, false, null)); const token_action = txEnvelope.transactionEnvelope.payload.data.token_action; const action_data = token_action[token_action.data]; - t.equals(token_action.data, commandName, 'Validating token transaction matches the command name'); + t.equals(token_action.data, commandName, 'Validating token transaction matches command name ' + commandName); t.equals(action_data.outputs.length, expectedOutputs.length, 'Validationing number of outputs in token transaction'); for (let i = 0; i < expectedOutputs.length; i++) { - t.deepEqual(action_data.outputs[i], expectedOutputs[i], 'Validationing output in token transaction'); + // fabtoken uses hex string in token transaction, so convert expectedQuantity to hex string + const expectedQuantityToHex = tokenUtils.toHex(parseInt(expectedOutputs[i].quantity)); + t.deepEqual(action_data.outputs[i].quantity, expectedQuantityToHex, 'Validationing quantity in token transaction'); + t.deepEqual(action_data.outputs[i].owner, expectedOutputs[i].owner, 'Validationing owner in token transaction'); + t.deepEqual(action_data.outputs[i].type, expectedOutputs[i].type, 'Validationing type in token transaction'); } if (expectedInputs) { t.deepEqual(action_data.inputs, expectedInputs, 'Validationing inputs in token transaction');