From 6875049c8de49dec3335363aabc0e2920cd81235 Mon Sep 17 00:00:00 2001 From: nikhil550 Date: Mon, 1 Feb 2021 04:19:45 -0500 Subject: [PATCH] Auction sample clean up (#408) Signed-off-by: Nikhil Gupta Co-authored-by: Nikhil Gupta --- auction/README.md | 138 +++++++++--------- auction/application-javascript/bid.js | 17 +-- .../application-javascript/closeAuction.js | 16 +- .../application-javascript/createAuction.js | 14 +- auction/application-javascript/endAuction.js | 16 +- auction/application-javascript/enrollAdmin.js | 9 -- .../application-javascript/queryAuction.js | 14 +- auction/application-javascript/queryBid.js | 14 +- .../registerEnrollUser.js | 9 -- auction/application-javascript/revealBid.js | 14 +- .../chaincode-go/smart-contract/auction.go | 129 ++++++---------- .../smart-contract/auctionQueries.go | 18 +-- auction/chaincode-go/smart-contract/utils.go | 14 ++ 13 files changed, 146 insertions(+), 276 deletions(-) diff --git a/auction/README.md b/auction/README.md index 73891727..bd6bb0d9 100644 --- a/auction/README.md +++ b/auction/README.md @@ -82,7 +82,7 @@ After the transaction is complete, the `createAuction.js` application will query *** Result: Auction: { "objectType": "auction", "item": "painting", - "seller": "eDUwOTo6Q049c2VsbGVyLE9VPWNsaWVudCtPVT1vcmcxK09VPWRlcGFydG1lbnQxOjpDTj1jYS5vcmcxLmV4YW1wbGUuY29tLE89b3JnMS5leGFtcGxlLmNvbSxMPUR1cmhhbSxTVD1Ob3J0aCBDYXJvbGluYSxDPVVT", + "seller": "x509::CN=seller,OU=client+OU=org1+OU=department1::CN=ca.org1.example.com,O=org1.example.com,L=Durham,ST=North Carolina,C=US", "organizations": [ "Org1MSP" ], @@ -93,16 +93,7 @@ After the transaction is complete, the `createAuction.js` application will query "status": "open" } ``` -The smart contract uses the `GetClientIdentity().GetID()` API to read identity that creates the auction and defines that identity as the auction `"seller"`. You can see the seller information by decoding the `"seller"` string out of base64 format: - -``` -echo eDUwOTo6Q049c2VsbGVyLE9VPWNsaWVudCtPVT1vcmcxK09VPWRlcGFydG1lbnQxOjpDTj1jYS5vcmcxLmV4YW1wbGUuY29tLE89b3JnMS5leGFtcGxlLmNvbSxMPUR1cmhhbSxTVD1Ob3J0aCBDYXJvbGluYSxDPVVT | base64 --decode -``` - -The result is the name and issuer of the seller's certificate: -``` -x509::CN=org1admin,OU=admin,O=Hyperledger,ST=North Carolina,C=US::CN=ca.org1.example.com,O=org1.example.com,L=Durham,ST=North Carolina,C=USn -``` +The smart contract uses the `GetClientIdentity().GetID()` API to read the identity that creates the auction and defines that identity as the auction `"seller"`. The seller is identified by the name and issuer of the seller's certificate. ## Bid on the auction @@ -121,7 +112,7 @@ The application will query the bid after it is created: "objectType": "bid", "price": 800, "org": "Org1MSP", - "bidder": "eDUwOTo6Q049YmlkZGVyMSxPVT1jbGllbnQrT1U9b3JnMStPVT1kZXBhcnRtZW50MTo6Q049Y2Eub3JnMS5leGFtcGxlLmNvbSxPPW9yZzEuZXhhbXBsZS5jb20sTD1EdXJoYW0sU1Q9Tm9ydGggQ2Fyb2xpbmEsQz1VUw==" + "bidder": "x509::CN=bidder1,OU=client+OU=org1+OU=department1::CN=ca.org1.example.com,O=org1.example.com,L=Durham,ST=North Carolina,C=US" } ``` @@ -129,12 +120,12 @@ The bid is stored in the Org1 implicit data collection. The `"bidder"` parameter The `bid.js` application also prints the bidID: ``` -*** Result ***SAVE THIS VALUE*** BidID: 8ef83011a5fb791f75ed008337839426f6b87981519e5d58ef5ada39c3044edd +*** Result ***SAVE THIS VALUE*** BidID: 67d85ef08e32de20994c816362d0952fe5c2ae3f2d1083600c3ac61f65a89f60 ``` The BidID acts as the unique identifier for the bid. This ID allows you to query the bid using the `queryBid.js` program and add the bid to the auction. Save the bidID returned by the application as an environment variable in your terminal: ``` -export BIDDER1_BID_ID=8ef83011a5fb791f75ed008337839426f6b87981519e5d58ef5ada39c3044edd +export BIDDER1_BID_ID=67d85ef08e32de20994c816362d0952fe5c2ae3f2d1083600c3ac61f65a89f60 ``` This value will be different for each transaction, so you will need to use the value returned in your terminal. @@ -148,14 +139,14 @@ The hash of bid will be added to the list private bids in that have been submitt *** Result: Auction: { "objectType": "auction", "item": "painting", - "seller": "eDUwOTo6Q049c2VsbGVyLE9VPWNsaWVudCtPVT1vcmcxK09VPWRlcGFydG1lbnQxOjpDTj1jYS5vcmcxLmV4YW1wbGUuY29tLE89b3JnMS5leGFtcGxlLmNvbSxMPUR1cmhhbSxTVD1Ob3J0aCBDYXJvbGluYSxDPVVT", + "seller": "x509::CN=seller,OU=client+OU=org1+OU=department1::CN=ca.org1.example.com,O=org1.example.com,L=Durham,ST=North Carolina,C=US", "organizations": [ "Org1MSP" ], "privateBids": { - "\u0000bid\u0000PaintingAuction\u00008ef83011a5fb791f75ed008337839426f6b87981519e5d58ef5ada39c3044edd\u0000": { + "\u0000bid\u0000PaintingAuction\u00005c049b0b4552d34c88e0f8fb5abca31fa04472b7e1336a16650ac8cfb0b16472\u0000": { "org": "Org1MSP", - "hash": "5cb50a17b5a21c02fc01306e3e9b54f4db67e9a440552ce898bbd7daa62dce0f" + "hash": "0b8bbdb96b1d252e71ac1ed71df3580f7a0e31a743a4a09bbf5196dffef426b2" } }, "revealedBids": {}, @@ -174,7 +165,7 @@ node bid.js org1 bidder2 PaintingAuction 500 Save the Bid ID returned by the application: ``` -export BIDDER2_BID_ID=915a908c8f2c368f4a3aedd73176656af81ddfab000b11629503403f3d97b185 +export BIDDER2_BID_ID=0fa8b3b15923966f205a1f5ebd163d2707d069ffa055105114fc654d225f511d ``` Submit bidder2's bid to the auction: @@ -191,7 +182,7 @@ node bid.js org2 bidder3 PaintingAuction 700 Save the Bid ID returned by the application: ``` -export BIDDER3_BID_ID=5e4e637c68833b178739575f6fe09820b019551a8cfbb43a4d172e0aa864dfad +export BIDDER3_BID_ID=cda8bb2849fc0553efb036c56ea86d82791a695b5641941dac797dc6e2d75768 ``` Add bidder3's bid to the auction: @@ -204,23 +195,23 @@ Because bidder3 belongs to Org2, submitting the bid will add Org2 to the list of *** Result: Auction: { "objectType": "auction", "item": "painting", - "seller": "eDUwOTo6Q049c2VsbGVyLE9VPWNsaWVudCtPVT1vcmcxK09VPWRlcGFydG1lbnQxOjpDTj1jYS5vcmcxLmV4YW1wbGUuY29tLE89b3JnMS5leGFtcGxlLmNvbSxMPUR1cmhhbSxTVD1Ob3J0aCBDYXJvbGluYSxDPVVT", + "seller": "x509::CN=seller,OU=client+OU=org1+OU=department1::CN=ca.org1.example.com,O=org1.example.com,L=Durham,ST=North Carolina,C=US", "organizations": [ "Org1MSP", "Org2MSP" ], "privateBids": { - "\u0000bid\u0000PaintingAuction\u00005e4e637c68833b178739575f6fe09820b019551a8cfbb43a4d172e0aa864dfad\u0000": { + "\u0000bid\u0000PaintingAuction\u00001b9dc0006fef10413df5cca927cabdf73ab854fe92b7a7b2eebfa00961fdac67\u0000": { + "org": "Org1MSP", + "hash": "15cd9a3e12825017f3e758499ac6138ebbe1adec4c49cc6ea6a0973fc6514666" + }, + "\u0000bid\u0000PaintingAuction\u00005c049b0b4552d34c88e0f8fb5abca31fa04472b7e1336a16650ac8cfb0b16472\u0000": { + "org": "Org1MSP", + "hash": "0b8bbdb96b1d252e71ac1ed71df3580f7a0e31a743a4a09bbf5196dffef426b2" + }, + "\u0000bid\u0000PaintingAuction\u00005ee4fa53b54ea0821e57a6884a1ada5eb04f136ee222e92d7399bcdf47556ea1\u0000": { "org": "Org2MSP", - "hash": "40107eab7a99dfc2f25d02b8ab840f12fd802a9f86d8d42b78d7b4409b2c15bd" - }, - "\u0000bid\u0000PaintingAuction\u00008ef83011a5fb791f75ed008337839426f6b87981519e5d58ef5ada39c3044edd\u0000": { - "org": "Org1MSP", - "hash": "5cb50a17b5a21c02fc01306e3e9b54f4db67e9a440552ce898bbd7daa62dce0f" - }, - "\u0000bid\u0000PaintingAuction\u0000915a908c8f2c368f4a3aedd73176656af81ddfab000b11629503403f3d97b185\u0000": { - "org": "Org1MSP", - "hash": "a458df18b12dffe4ae6d56a270134c2d55bd53fface034bd24381d0073d46a45" + "hash": "14d47d17acceceb483e87c14a4349844874fce549d71c6a23457d953ed8ffbd3" } }, "revealedBids": {}, @@ -241,7 +232,7 @@ node bid.js org2 bidder4 PaintingAuction 900 Save the Bid ID returned by the application: ``` -export BIDDER4_BID_ID=49466271ae879bd009e75a60730a12bfa986e75f263202ab81ccd3deec544a35 +export BIDDER4_BID_ID=83861eb17715ff537a1e73cd2d08509dc7199572806a5368706516759af1a257 ``` Add bidder4's bid to the auction: @@ -276,35 +267,35 @@ The full bid details, including the price, are now visible: *** Result: Auction: { "objectType": "auction", "item": "painting", - "seller": "eDUwOTo6Q049c2VsbGVyLE9VPWNsaWVudCtPVT1vcmcxK09VPWRlcGFydG1lbnQxOjpDTj1jYS5vcmcxLmV4YW1wbGUuY29tLE89b3JnMS5leGFtcGxlLmNvbSxMPUR1cmhhbSxTVD1Ob3J0aCBDYXJvbGluYSxDPVVT", + "seller": "x509::CN=seller,OU=client+OU=org1+OU=department1::CN=ca.org1.example.com,O=org1.example.com,L=Durham,ST=North Carolina,C=US", "organizations": [ "Org1MSP", "Org2MSP" ], "privateBids": { - "\u0000bid\u0000PaintingAuction\u000049466271ae879bd009e75a60730a12bfa986e75f263202ab81ccd3deec544a35\u0000": { + "\u0000bid\u0000PaintingAuction\u000019a7a0dd2c5456a3f79c2f9ccb09dddd0f1c9ece514dfea7cbea06e7cbc79855\u0000": { "org": "Org2MSP", - "hash": "b8eaeb4422b93abdfe4ccb6aa11b745b3d1cb072a99bd3eb3618f081fb1b1f89" + "hash": "08db66c6cc226577a3153dadeb0b77d3834162fcf5f008b344058a1bc5c1b3a4" }, - "\u0000bid\u0000PaintingAuction\u00005e4e637c68833b178739575f6fe09820b019551a8cfbb43a4d172e0aa864dfad\u0000": { + "\u0000bid\u0000PaintingAuction\u00001b9dc0006fef10413df5cca927cabdf73ab854fe92b7a7b2eebfa00961fdac67\u0000": { + "org": "Org1MSP", + "hash": "15cd9a3e12825017f3e758499ac6138ebbe1adec4c49cc6ea6a0973fc6514666" + }, + "\u0000bid\u0000PaintingAuction\u00005c049b0b4552d34c88e0f8fb5abca31fa04472b7e1336a16650ac8cfb0b16472\u0000": { + "org": "Org1MSP", + "hash": "0b8bbdb96b1d252e71ac1ed71df3580f7a0e31a743a4a09bbf5196dffef426b2" + }, + "\u0000bid\u0000PaintingAuction\u00005ee4fa53b54ea0821e57a6884a1ada5eb04f136ee222e92d7399bcdf47556ea1\u0000": { "org": "Org2MSP", - "hash": "40107eab7a99dfc2f25d02b8ab840f12fd802a9f86d8d42b78d7b4409b2c15bd" - }, - "\u0000bid\u0000PaintingAuction\u00008ef83011a5fb791f75ed008337839426f6b87981519e5d58ef5ada39c3044edd\u0000": { - "org": "Org1MSP", - "hash": "5cb50a17b5a21c02fc01306e3e9b54f4db67e9a440552ce898bbd7daa62dce0f" - }, - "\u0000bid\u0000PaintingAuction\u0000915a908c8f2c368f4a3aedd73176656af81ddfab000b11629503403f3d97b185\u0000": { - "org": "Org1MSP", - "hash": "a458df18b12dffe4ae6d56a270134c2d55bd53fface034bd24381d0073d46a45" + "hash": "14d47d17acceceb483e87c14a4349844874fce549d71c6a23457d953ed8ffbd3" } }, "revealedBids": { - "\u0000bid\u0000PaintingAuction\u00008ef83011a5fb791f75ed008337839426f6b87981519e5d58ef5ada39c3044edd\u0000": { + "\u0000bid\u0000PaintingAuction\u00005c049b0b4552d34c88e0f8fb5abca31fa04472b7e1336a16650ac8cfb0b16472\u0000": { "objectType": "bid", "price": 800, "org": "Org1MSP", - "bidder": "eDUwOTo6Q049YmlkZGVyMSxPVT1jbGllbnQrT1U9b3JnMStPVT1kZXBhcnRtZW50MTo6Q049Y2Eub3JnMS5leGFtcGxlLmNvbSxPPW9yZzEuZXhhbXBsZS5jb20sTD1EdXJoYW0sU1Q9Tm9ydGggQ2Fyb2xpbmEsQz1VUw==" + "bidder": "x509::CN=bidder1,OU=client+OU=org1+OU=department1::CN=ca.org1.example.com,O=org1.example.com,L=Durham,ST=North Carolina,C=US" } }, "winner": "", @@ -328,8 +319,11 @@ The output should look something like the following: ``` --> Submit the transaction to end the auction -2020-11-06T13:16:11.591Z - warn: [TransactionEventHandler]: strategyFail: commit failure for transaction "99feade5b7ec223839200867b57d18971c3e9f923efc95aaeec720727f927366": TransactionError: Commit of transaction 99feade5b7ec223839200867b57d18971c3e9f923efc95aaeec720727f927366 failed on peer peer0.org1.example.com:7051 with status ENDORSEMENT_POLICY_FAILURE -******** FAILED to submit bid: TransactionError: Commit of transaction 99feade5b7ec223839200867b57d18971c3e9f923efc95aaeec720727f927366 failed on peer peer0.org1.example.com:7051 with status ENDORSEMENT_POLICY_FAILURE +2021-01-28T16:47:27.501Z - error: [DiscoveryHandler]: compareProposalResponseResults[undefined] - read/writes result sets do not match index=1 +2021-01-28T16:47:27.503Z - error: [Transaction]: Error: No valid responses from any peers. Errors: + peer=undefined, status=grpc, message=Peer endorsements do not match +******** FAILED to submit bid: Error: No valid responses from any peers. Errors: + peer=undefined, status=grpc, message=Peer endorsements do not match ``` Instead of ending the auction, the transaction results in an endorsement policy failure. The end of the auction needs to be endorsed by Org2. Before endorsing the transaction, the Org2 peer queries its private data collection for any winning bids that have not yet been revealed. Because Bidder4 created a bid that is above the winning price, the Org2 peer refuses to endorse the transaction that would end the auction. @@ -353,50 +347,50 @@ The transaction was successfully endorsed by both Org1 and Org2, who both calcul *** Result: Auction: { "objectType": "auction", "item": "painting", - "seller": "eDUwOTo6Q049c2VsbGVyLE9VPWNsaWVudCtPVT1vcmcxK09VPWRlcGFydG1lbnQxOjpDTj1jYS5vcmcxLmV4YW1wbGUuY29tLE89b3JnMS5leGFtcGxlLmNvbSxMPUR1cmhhbSxTVD1Ob3J0aCBDYXJvbGluYSxDPVVT", + "seller": "x509::CN=seller,OU=client+OU=org1+OU=department1::CN=ca.org1.example.com,O=org1.example.com,L=Durham,ST=North Carolina,C=US", "organizations": [ "Org1MSP", "Org2MSP" ], "privateBids": { - "\u0000bid\u0000PaintingAuction\u000049466271ae879bd009e75a60730a12bfa986e75f263202ab81ccd3deec544a35\u0000": { + "\u0000bid\u0000PaintingAuction\u000019a7a0dd2c5456a3f79c2f9ccb09dddd0f1c9ece514dfea7cbea06e7cbc79855\u0000": { "org": "Org2MSP", - "hash": "b8eaeb4422b93abdfe4ccb6aa11b745b3d1cb072a99bd3eb3618f081fb1b1f89" + "hash": "08db66c6cc226577a3153dadeb0b77d3834162fcf5f008b344058a1bc5c1b3a4" }, - "\u0000bid\u0000PaintingAuction\u00005e4e637c68833b178739575f6fe09820b019551a8cfbb43a4d172e0aa864dfad\u0000": { + "\u0000bid\u0000PaintingAuction\u00001b9dc0006fef10413df5cca927cabdf73ab854fe92b7a7b2eebfa00961fdac67\u0000": { + "org": "Org1MSP", + "hash": "15cd9a3e12825017f3e758499ac6138ebbe1adec4c49cc6ea6a0973fc6514666" + }, + "\u0000bid\u0000PaintingAuction\u00005c049b0b4552d34c88e0f8fb5abca31fa04472b7e1336a16650ac8cfb0b16472\u0000": { + "org": "Org1MSP", + "hash": "0b8bbdb96b1d252e71ac1ed71df3580f7a0e31a743a4a09bbf5196dffef426b2" + }, + "\u0000bid\u0000PaintingAuction\u00005ee4fa53b54ea0821e57a6884a1ada5eb04f136ee222e92d7399bcdf47556ea1\u0000": { "org": "Org2MSP", - "hash": "40107eab7a99dfc2f25d02b8ab840f12fd802a9f86d8d42b78d7b4409b2c15bd" - }, - "\u0000bid\u0000PaintingAuction\u00008ef83011a5fb791f75ed008337839426f6b87981519e5d58ef5ada39c3044edd\u0000": { - "org": "Org1MSP", - "hash": "5cb50a17b5a21c02fc01306e3e9b54f4db67e9a440552ce898bbd7daa62dce0f" - }, - "\u0000bid\u0000PaintingAuction\u0000915a908c8f2c368f4a3aedd73176656af81ddfab000b11629503403f3d97b185\u0000": { - "org": "Org1MSP", - "hash": "a458df18b12dffe4ae6d56a270134c2d55bd53fface034bd24381d0073d46a45" + "hash": "14d47d17acceceb483e87c14a4349844874fce549d71c6a23457d953ed8ffbd3" } }, "revealedBids": { - "\u0000bid\u0000PaintingAuction\u000049466271ae879bd009e75a60730a12bfa986e75f263202ab81ccd3deec544a35\u0000": { + "\u0000bid\u0000PaintingAuction\u000019a7a0dd2c5456a3f79c2f9ccb09dddd0f1c9ece514dfea7cbea06e7cbc79855\u0000": { "objectType": "bid", "price": 900, "org": "Org2MSP", - "bidder": "eDUwOTo6Q049YmlkZGVyNCxPVT1jbGllbnQrT1U9b3JnMitPVT1kZXBhcnRtZW50MTo6Q049Y2Eub3JnMi5leGFtcGxlLmNvbSxPPW9yZzIuZXhhbXBsZS5jb20sTD1IdXJzbGV5LFNUPUhhbXBzaGlyZSxDPVVL" + "bidder": "x509::CN=bidder4,OU=client+OU=org2+OU=department1::CN=ca.org2.example.com,O=org2.example.com,L=Hursley,ST=Hampshire,C=UK" }, - "\u0000bid\u0000PaintingAuction\u00005e4e637c68833b178739575f6fe09820b019551a8cfbb43a4d172e0aa864dfad\u0000": { - "objectType": "bid", - "price": 700, - "org": "Org2MSP", - "bidder": "eDUwOTo6Q049YmlkZGVyMyxPVT1jbGllbnQrT1U9b3JnMitPVT1kZXBhcnRtZW50MTo6Q049Y2Eub3JnMi5leGFtcGxlLmNvbSxPPW9yZzIuZXhhbXBsZS5jb20sTD1IdXJzbGV5LFNUPUhhbXBzaGlyZSxDPVVL" - }, - "\u0000bid\u0000PaintingAuction\u00008ef83011a5fb791f75ed008337839426f6b87981519e5d58ef5ada39c3044edd\u0000": { + "\u0000bid\u0000PaintingAuction\u00005c049b0b4552d34c88e0f8fb5abca31fa04472b7e1336a16650ac8cfb0b16472\u0000": { "objectType": "bid", "price": 800, "org": "Org1MSP", - "bidder": "eDUwOTo6Q049YmlkZGVyMSxPVT1jbGllbnQrT1U9b3JnMStPVT1kZXBhcnRtZW50MTo6Q049Y2Eub3JnMS5leGFtcGxlLmNvbSxPPW9yZzEuZXhhbXBsZS5jb20sTD1EdXJoYW0sU1Q9Tm9ydGggQ2Fyb2xpbmEsQz1VUw==" + "bidder": "x509::CN=bidder1,OU=client+OU=org1+OU=department1::CN=ca.org1.example.com,O=org1.example.com,L=Durham,ST=North Carolina,C=US" + }, + "\u0000bid\u0000PaintingAuction\u00005ee4fa53b54ea0821e57a6884a1ada5eb04f136ee222e92d7399bcdf47556ea1\u0000": { + "objectType": "bid", + "price": 700, + "org": "Org2MSP", + "bidder": "x509::CN=bidder3,OU=client+OU=org2+OU=department1::CN=ca.org2.example.com,O=org2.example.com,L=Hursley,ST=Hampshire,C=UK" } }, - "winner": "eDUwOTo6Q049YmlkZGVyNCxPVT1jbGllbnQrT1U9b3JnMitPVT1kZXBhcnRtZW50MTo6Q049Y2Eub3JnMi5leGFtcGxlLmNvbSxPPW9yZzIuZXhhbXBsZS5jb20sTD1IdXJzbGV5LFNUPUhhbXBzaGlyZSxDPVVL", + "winner": "x509::CN=bidder4,OU=client+OU=org2+OU=department1::CN=ca.org2.example.com,O=org2.example.com,L=Hursley,ST=Hampshire,C=UK", "price": 900, "status": "ended" } diff --git a/auction/application-javascript/bid.js b/auction/application-javascript/bid.js index a5540d80..81d0af92 100644 --- a/auction/application-javascript/bid.js +++ b/auction/application-javascript/bid.js @@ -8,21 +8,11 @@ const { Gateway, Wallets } = require('fabric-network'); const path = require('path'); -const { buildCCPOrg1, buildCCPOrg2, buildWallet } = require('../../test-application/javascript/AppUtil.js'); +const { buildCCPOrg1, buildCCPOrg2, buildWallet, prettyJSONString} = require('../../test-application/javascript/AppUtil.js'); const myChannel = 'mychannel'; const myChaincodeName = 'auction'; - -function prettyJSONString(inputString) { - if (inputString) { - return JSON.stringify(JSON.parse(inputString), null, 2); - } - else { - return inputString; - } -} - async function bid(ccp,wallet,user,orgMSP,auctionID,price) { try { @@ -36,7 +26,7 @@ async function bid(ccp,wallet,user,orgMSP,auctionID,price) { const contract = network.getContract(myChaincodeName); console.log('\n--> Evaluate Transaction: get your client ID'); - let bidder = await contract.evaluateTransaction('GetID'); + let bidder = await contract.evaluateTransaction('GetSubmittingClientIdentity'); console.log('*** Result: Bidder ID is ' + bidder.toString()); let bidData = { objectType: 'bid', price: parseInt(price), org: orgMSP, bidder: bidder.toString()}; @@ -78,7 +68,7 @@ async function main() { process.exit(1); } - const org = process.argv[2] + const org = process.argv[2]; const user = process.argv[3]; const auctionID = process.argv[4]; const price = process.argv[5]; @@ -108,5 +98,4 @@ async function main() { } } - main(); diff --git a/auction/application-javascript/closeAuction.js b/auction/application-javascript/closeAuction.js index 7934fbf5..ad940d92 100644 --- a/auction/application-javascript/closeAuction.js +++ b/auction/application-javascript/closeAuction.js @@ -8,21 +8,11 @@ const { Gateway, Wallets } = require('fabric-network'); const path = require('path'); -const { buildCCPOrg1, buildCCPOrg2, buildWallet } = require('../../test-application/javascript/AppUtil.js'); +const { buildCCPOrg1, buildCCPOrg2, buildWallet, prettyJSONString} = require('../../test-application/javascript/AppUtil.js'); const myChannel = 'mychannel'; const myChaincodeName = 'auction'; - -function prettyJSONString(inputString) { - if (inputString) { - return JSON.stringify(JSON.parse(inputString), null, 2); - } - else { - return inputString; - } -} - async function closeAuction(ccp,wallet,user,auctionID) { try { @@ -36,9 +26,7 @@ async function closeAuction(ccp,wallet,user,auctionID) { const contract = network.getContract(myChaincodeName); // Query the auction to get the list of endorsing orgs. - //console.log('\n--> Evaluate Transaction: query the auction you want to close'); let auctionString = await contract.evaluateTransaction('QueryAuction',auctionID); - //console.log('*** Result: Bid: ' + prettyJSONString(auctionString.toString())); var auctionJSON = JSON.parse(auctionString); let statefulTxn = contract.createTransaction('CloseAuction'); @@ -73,7 +61,7 @@ async function main() { process.exit(1); } - const org = process.argv[2] + const org = process.argv[2]; const user = process.argv[3]; const auctionID = process.argv[4]; diff --git a/auction/application-javascript/createAuction.js b/auction/application-javascript/createAuction.js index 8d083d70..470d3dca 100644 --- a/auction/application-javascript/createAuction.js +++ b/auction/application-javascript/createAuction.js @@ -8,21 +8,11 @@ const { Gateway, Wallets } = require('fabric-network'); const path = require('path'); -const { buildCCPOrg1, buildCCPOrg2, buildWallet } = require('../../test-application/javascript/AppUtil.js'); +const { buildCCPOrg1, buildCCPOrg2, buildWallet, prettyJSONString} = require('../../test-application/javascript/AppUtil.js'); const myChannel = 'mychannel'; const myChaincodeName = 'auction'; - -function prettyJSONString(inputString) { - if (inputString) { - return JSON.stringify(JSON.parse(inputString), null, 2); - } - else { - return inputString; - } -} - async function createAuction(ccp,wallet,user,auctionID,item) { try { @@ -60,7 +50,7 @@ async function main() { process.exit(1); } - const org = process.argv[2] + const org = process.argv[2]; const user = process.argv[3]; const auctionID = process.argv[4]; const item = process.argv[5]; diff --git a/auction/application-javascript/endAuction.js b/auction/application-javascript/endAuction.js index 3c16c7fc..b5fd51c8 100644 --- a/auction/application-javascript/endAuction.js +++ b/auction/application-javascript/endAuction.js @@ -8,21 +8,11 @@ const { Gateway, Wallets } = require('fabric-network'); const path = require('path'); -const { buildCCPOrg1, buildCCPOrg2, buildWallet } = require('../../test-application/javascript/AppUtil.js'); +const { buildCCPOrg1, buildCCPOrg2, buildWallet, prettyJSONString} = require('../../test-application/javascript/AppUtil.js'); const myChannel = 'mychannel'; const myChaincodeName = 'auction'; - -function prettyJSONString(inputString) { - if (inputString) { - return JSON.stringify(JSON.parse(inputString), null, 2); - } - else { - return inputString; - } -} - async function endAuction(ccp,wallet,user,auctionID) { try { @@ -36,9 +26,7 @@ async function endAuction(ccp,wallet,user,auctionID) { const contract = network.getContract(myChaincodeName); // Query the auction to get the list of endorsing orgs. - //console.log('\n--> Evaluate Transaction: query the auction you want to end'); let auctionString = await contract.evaluateTransaction('QueryAuction',auctionID); - //console.log('*** Result: Bid: ' + prettyJSONString(auctionString.toString())); var auctionJSON = JSON.parse(auctionString); let statefulTxn = contract.createTransaction('EndAuction'); @@ -73,7 +61,7 @@ async function main() { process.exit(1); } - const org = process.argv[2] + const org = process.argv[2]; const user = process.argv[3]; const auctionID = process.argv[4]; diff --git a/auction/application-javascript/enrollAdmin.js b/auction/application-javascript/enrollAdmin.js index e2df9cfb..8fa34071 100644 --- a/auction/application-javascript/enrollAdmin.js +++ b/auction/application-javascript/enrollAdmin.js @@ -15,15 +15,6 @@ const { buildCCPOrg1, buildCCPOrg2, buildWallet } = require('../../test-applicat const mspOrg1 = 'Org1MSP'; const mspOrg2 = 'Org2MSP'; -function prettyJSONString(inputString) { - if (inputString) { - return JSON.stringify(JSON.parse(inputString), null, 2); - } - else { - return inputString; - } -} - async function connectToOrg1CA() { console.log('\n--> Enrolling the Org1 CA admin'); const ccpOrg1 = buildCCPOrg1(); diff --git a/auction/application-javascript/queryAuction.js b/auction/application-javascript/queryAuction.js index 258d19c1..6bca2d19 100644 --- a/auction/application-javascript/queryAuction.js +++ b/auction/application-javascript/queryAuction.js @@ -8,21 +8,11 @@ const { Gateway, Wallets } = require('fabric-network'); const path = require('path'); -const { buildCCPOrg1, buildCCPOrg2, buildWallet } = require('../../test-application/javascript/AppUtil.js'); +const { buildCCPOrg1, buildCCPOrg2, buildWallet, prettyJSONString} = require('../../test-application/javascript/AppUtil.js'); const myChannel = 'mychannel'; const myChaincodeName = 'auction'; - -function prettyJSONString(inputString) { - if (inputString) { - return JSON.stringify(JSON.parse(inputString), null, 2); - } - else { - return inputString; - } -} - async function queryAuction(ccp,wallet,user,auctionID) { try { @@ -54,7 +44,7 @@ async function main() { process.exit(1); } - const org = process.argv[2] + const org = process.argv[2]; const user = process.argv[3]; const auctionID = process.argv[4]; diff --git a/auction/application-javascript/queryBid.js b/auction/application-javascript/queryBid.js index b4ffea69..6af90137 100644 --- a/auction/application-javascript/queryBid.js +++ b/auction/application-javascript/queryBid.js @@ -8,21 +8,11 @@ const { Gateway, Wallets } = require('fabric-network'); const path = require('path'); -const { buildCCPOrg1, buildCCPOrg2, buildWallet } = require('../../test-application/javascript/AppUtil.js'); +const { buildCCPOrg1, buildCCPOrg2, buildWallet, prettyJSONString} = require('../../test-application/javascript/AppUtil.js'); const myChannel = 'mychannel'; const myChaincodeName = 'auction'; - -function prettyJSONString(inputString) { - if (inputString) { - return JSON.stringify(JSON.parse(inputString), null, 2); - } - else { - return inputString; - } -} - async function queryBid(ccp,wallet,user,auctionID,bidID) { try { @@ -54,7 +44,7 @@ async function main() { process.exit(1); } - const org = process.argv[2] + const org = process.argv[2]; const user = process.argv[3]; const auctionID = process.argv[4]; const bidID = process.argv[5]; diff --git a/auction/application-javascript/registerEnrollUser.js b/auction/application-javascript/registerEnrollUser.js index 3ee97a6a..ba131f6c 100644 --- a/auction/application-javascript/registerEnrollUser.js +++ b/auction/application-javascript/registerEnrollUser.js @@ -15,15 +15,6 @@ const { buildCCPOrg1, buildCCPOrg2, buildWallet } = require('../../test-applicat const mspOrg1 = 'Org1MSP'; const mspOrg2 = 'Org2MSP'; -function prettyJSONString(inputString) { - if (inputString) { - return JSON.stringify(JSON.parse(inputString), null, 2); - } - else { - return inputString; - } -} - async function connectToOrg1CA(UserID) { console.log('\n--> Register and enrolling new user'); const ccpOrg1 = buildCCPOrg1(); diff --git a/auction/application-javascript/revealBid.js b/auction/application-javascript/revealBid.js index 8b397439..c66cd704 100644 --- a/auction/application-javascript/revealBid.js +++ b/auction/application-javascript/revealBid.js @@ -8,21 +8,11 @@ const { Gateway, Wallets } = require('fabric-network'); const path = require('path'); -const { buildCCPOrg1, buildCCPOrg2, buildWallet } = require('../../test-application/javascript/AppUtil.js'); +const { buildCCPOrg1, buildCCPOrg2, buildWallet, prettyJSONString} = require('../../test-application/javascript/AppUtil.js'); const myChannel = 'mychannel'; const myChaincodeName = 'auction'; - -function prettyJSONString(inputString) { - if (inputString) { - return JSON.stringify(JSON.parse(inputString), null, 2); - } - else { - return inputString; - } -} - async function addBid(ccp,wallet,user,auctionID,bidID) { try { @@ -81,7 +71,7 @@ async function main() { process.exit(1); } - const org = process.argv[2] + const org = process.argv[2]; const user = process.argv[3]; const auctionID = process.argv[4]; const bidID = process.argv[5]; diff --git a/auction/chaincode-go/smart-contract/auction.go b/auction/chaincode-go/smart-contract/auction.go index c197e7e5..5657235d 100644 --- a/auction/chaincode-go/smart-contract/auction.go +++ b/auction/chaincode-go/smart-contract/auction.go @@ -51,7 +51,7 @@ const bidKeyType = "bid" func (s *SmartContract) CreateAuction(ctx contractapi.TransactionContextInterface, auctionID string, itemsold string) error { // get ID of submitting client - clientID, err := ctx.GetClientIdentity().GetID() + clientID, err := s.GetSubmittingClientIdentity(ctx) if err != nil { return fmt.Errorf("failed to get client identity %v", err) } @@ -78,13 +78,13 @@ func (s *SmartContract) CreateAuction(ctx contractapi.TransactionContextInterfac Status: "open", } - auctionBytes, err := json.Marshal(auction) + auctionJSON, err := json.Marshal(auction) if err != nil { return err } // put auction into state - err = ctx.GetStub().PutState(auctionID, auctionBytes) + err = ctx.GetStub().PutState(auctionID, auctionJSON) if err != nil { return fmt.Errorf("failed to put auction in public data: %v", err) } @@ -156,20 +156,14 @@ func (s *SmartContract) SubmitBid(ctx contractapi.TransactionContextInterface, a return fmt.Errorf("failed to get client MSP ID: %v", err) } - // get the auction from state - auctionBytes, err := ctx.GetStub().GetState(auctionID) - var auctionJSON Auction - - if auctionBytes == nil { - return fmt.Errorf("Auction not found: %v", auctionID) - } - err = json.Unmarshal(auctionBytes, &auctionJSON) + // get the auction from public state + auction, err := s.QueryAuction(ctx,auctionID) if err != nil { - return fmt.Errorf("failed to create auction object JSON: %v", err) + return fmt.Errorf("failed to get auction from public state %v", err) } // the auction needs to be open for users to add their bid - Status := auctionJSON.Status + Status := auction.Status if Status != "open" { return fmt.Errorf("cannot join closed or ended auction") } @@ -202,15 +196,15 @@ func (s *SmartContract) SubmitBid(ctx contractapi.TransactionContextInterface, a } bidders := make(map[string]BidHash) - bidders = auctionJSON.PrivateBids + bidders = auction.PrivateBids bidders[bidKey] = NewHash - auctionJSON.PrivateBids = bidders + auction.PrivateBids = bidders // Add the bidding organization to the list of participating organizations if it is not already - Orgs := auctionJSON.Orgs + Orgs := auction.Orgs if !(contains(Orgs, clientOrgID)) { newOrgs := append(Orgs, clientOrgID) - auctionJSON.Orgs = newOrgs + auction.Orgs = newOrgs err = addAssetStateBasedEndorsement(ctx, auctionID, clientOrgID) if err != nil { @@ -218,9 +212,9 @@ func (s *SmartContract) SubmitBid(ctx contractapi.TransactionContextInterface, a } } - newAuctionBytes, _ := json.Marshal(auctionJSON) + newAuctionJSON, _ := json.Marshal(auction) - err = ctx.GetStub().PutState(auctionID, newAuctionBytes) + err = ctx.GetStub().PutState(auctionID, newAuctionJSON) if err != nil { return fmt.Errorf("failed to update auction: %v", err) } @@ -264,25 +258,16 @@ func (s *SmartContract) RevealBid(ctx contractapi.TransactionContextInterface, a } // get auction from public state - auctionBytes, err := ctx.GetStub().GetState(auctionID) + auction, err := s.QueryAuction(ctx,auctionID) if err != nil { - return fmt.Errorf("failed to get auction %v: %v", auctionID, err) - } - if auctionBytes == nil { - return fmt.Errorf("Auction interest object %v not found", auctionID) - } - - var auctionJSON Auction - err = json.Unmarshal(auctionBytes, &auctionJSON) - if err != nil { - return fmt.Errorf("failed to create auction object JSON: %v", err) + return fmt.Errorf("failed to get auction from public state %v", err) } // Complete a series of three checks before we add the bid to the auction // check 1: check that the auction is closed. We cannot reveal a // bid to an open auction - Status := auctionJSON.Status + Status := auction.Status if Status != "closed" { return fmt.Errorf("cannot reveal bid for open or ended auction") } @@ -308,7 +293,7 @@ func (s *SmartContract) RevealBid(ctx contractapi.TransactionContextInterface, a // added earlier. This ensures that the bid has not changed since it // was added to the auction - bidders := auctionJSON.PrivateBids + bidders := auction.PrivateBids privateBidHashString := bidders[bidKey].Hash onChainBidHashString := fmt.Sprintf("%x", bidHash) @@ -335,7 +320,7 @@ func (s *SmartContract) RevealBid(ctx contractapi.TransactionContextInterface, a } // Get ID of submitting client identity - clientID, err := ctx.GetClientIdentity().GetID() + clientID, err := s.GetSubmittingClientIdentity(ctx) if err != nil { return fmt.Errorf("failed to get client identity %v", err) } @@ -354,14 +339,14 @@ func (s *SmartContract) RevealBid(ctx contractapi.TransactionContextInterface, a } revealedBids := make(map[string]FullBid) - revealedBids = auctionJSON.RevealedBids + revealedBids = auction.RevealedBids revealedBids[bidKey] = NewBid - auctionJSON.RevealedBids = revealedBids + auction.RevealedBids = revealedBids - newAuctionBytes, _ := json.Marshal(auctionJSON) + newAuctionJSON, _ := json.Marshal(auction) // put auction with bid added back into state - err = ctx.GetStub().PutState(auctionID, newAuctionBytes) + err = ctx.GetStub().PutState(auctionID, newAuctionJSON) if err != nil { return fmt.Errorf("failed to update auction: %v", err) } @@ -373,44 +358,35 @@ func (s *SmartContract) RevealBid(ctx contractapi.TransactionContextInterface, a // bids from being added to the auction, and allows users to reveal their bid func (s *SmartContract) CloseAuction(ctx contractapi.TransactionContextInterface, auctionID string) error { - auctionBytes, err := ctx.GetStub().GetState(auctionID) + // get auction from public state + auction, err := s.QueryAuction(ctx,auctionID) if err != nil { - return fmt.Errorf("failed to get auction %v: %v", auctionID, err) - } - - if auctionBytes == nil { - return fmt.Errorf("Auction interest object %v not found", auctionID) - } - - var auctionJSON Auction - err = json.Unmarshal(auctionBytes, &auctionJSON) - if err != nil { - return fmt.Errorf("failed to create auction object JSON: %v", err) + return fmt.Errorf("failed to get auction from public state %v", err) } // the auction can only be closed by the seller // get ID of submitting client - clientID, err := ctx.GetClientIdentity().GetID() + clientID, err := s.GetSubmittingClientIdentity(ctx) if err != nil { return fmt.Errorf("failed to get client identity %v", err) } - Seller := auctionJSON.Seller + Seller := auction.Seller if Seller != clientID { return fmt.Errorf("auction can only be closed by seller: %v", err) } - Status := auctionJSON.Status + Status := auction.Status if Status != "open" { return fmt.Errorf("cannot close auction that is not open") } - auctionJSON.Status = string("closed") + auction.Status = string("closed") - closedAuction, _ := json.Marshal(auctionJSON) + closedAuctionJSON, _ := json.Marshal(auction) - err = ctx.GetStub().PutState(auctionID, closedAuction) + err = ctx.GetStub().PutState(auctionID, closedAuctionJSON) if err != nil { return fmt.Errorf("failed to close auction: %v", err) } @@ -422,66 +398,57 @@ func (s *SmartContract) CloseAuction(ctx contractapi.TransactionContextInterface // of the auction func (s *SmartContract) EndAuction(ctx contractapi.TransactionContextInterface, auctionID string) error { - auctionBytes, err := ctx.GetStub().GetState(auctionID) + // get auction from public state + auction, err := s.QueryAuction(ctx,auctionID) if err != nil { - return fmt.Errorf("failed to get auction %v: %v", auctionID, err) - } - - if auctionBytes == nil { - return fmt.Errorf("Auction interest object %v not found", auctionID) - } - - var auctionJSON Auction - err = json.Unmarshal(auctionBytes, &auctionJSON) - if err != nil { - return fmt.Errorf("failed to create auction object JSON: %v", err) + return fmt.Errorf("failed to get auction from public state %v", err) } // Check that the auction is being ended by the seller // get ID of submitting client - clientID, err := ctx.GetClientIdentity().GetID() + clientID, err := s.GetSubmittingClientIdentity(ctx) if err != nil { return fmt.Errorf("failed to get client identity %v", err) } - Seller := auctionJSON.Seller + Seller := auction.Seller if Seller != clientID { return fmt.Errorf("auction can only be ended by seller: %v", err) } - Status := auctionJSON.Status + Status := auction.Status if Status != "closed" { return fmt.Errorf("Can only end a closed auction") } // get the list of revealed bids - revealedBidMap := auctionJSON.RevealedBids - if len(auctionJSON.RevealedBids) == 0 { + revealedBidMap := auction.RevealedBids + if len(auction.RevealedBids) == 0 { return fmt.Errorf("No bids have been revealed, cannot end auction: %v", err) } // determine the highest bid for _, bid := range revealedBidMap { - if bid.Price > auctionJSON.Price { - auctionJSON.Winner = bid.Bidder - auctionJSON.Price = bid.Price + if bid.Price > auction.Price { + auction.Winner = bid.Bidder + auction.Price = bid.Price } } // check if there is a winning bid that has yet to be revealed - err = queryAllBids(ctx, auctionJSON.Price, auctionJSON.RevealedBids, auctionJSON.PrivateBids) + err = checkForHigherBid(ctx, auction.Price, auction.RevealedBids, auction.PrivateBids) if err != nil { - return fmt.Errorf("Cannot close auction: %v", err) + return fmt.Errorf("Cannot end auction: %v", err) } - auctionJSON.Status = string("ended") + auction.Status = string("ended") - closedAuction, _ := json.Marshal(auctionJSON) + endedAuctionJSON, _ := json.Marshal(auction) - err = ctx.GetStub().PutState(auctionID, closedAuction) + err = ctx.GetStub().PutState(auctionID, endedAuctionJSON) if err != nil { - return fmt.Errorf("failed to close auction: %v", err) + return fmt.Errorf("failed to end auction: %v", err) } return nil } diff --git a/auction/chaincode-go/smart-contract/auctionQueries.go b/auction/chaincode-go/smart-contract/auctionQueries.go index 64eb45bf..1a72aec3 100644 --- a/auction/chaincode-go/smart-contract/auctionQueries.go +++ b/auction/chaincode-go/smart-contract/auctionQueries.go @@ -40,7 +40,7 @@ func (s *SmartContract) QueryBid(ctx contractapi.TransactionContextInterface, au return nil, fmt.Errorf("failed to get implicit collection name: %v", err) } - clientID, err := ctx.GetClientIdentity().GetID() + clientID, err := s.GetSubmittingClientIdentity(ctx) if err != nil { return nil, fmt.Errorf("failed to get client identity %v", err) } @@ -77,20 +77,8 @@ func (s *SmartContract) QueryBid(ctx contractapi.TransactionContextInterface, au return bid, nil } -// GetID is an internal helper function to allow users to get their identity -func (s *SmartContract) GetID(ctx contractapi.TransactionContextInterface) (string, error) { - - // Get the MSP ID of submitting client identity - clientID, err := ctx.GetClientIdentity().GetID() - if err != nil { - return "", fmt.Errorf("failed to get verified MSPID: %v", err) - } - - return clientID, nil -} - -// queryAllBids is an internal function that is used to determine if a winning bid has yet to be revealed -func queryAllBids(ctx contractapi.TransactionContextInterface, auctionPrice int, revealedBidders map[string]FullBid, bidders map[string]BidHash) error { +// checkForHigherBid is an internal function that is used to determine if a winning bid has yet to be revealed +func checkForHigherBid(ctx contractapi.TransactionContextInterface, auctionPrice int, revealedBidders map[string]FullBid, bidders map[string]BidHash) error { // Get MSP ID of peer org peerMSPID, err := shim.GetMSPID() diff --git a/auction/chaincode-go/smart-contract/utils.go b/auction/chaincode-go/smart-contract/utils.go index 8c305246..d3d3005b 100644 --- a/auction/chaincode-go/smart-contract/utils.go +++ b/auction/chaincode-go/smart-contract/utils.go @@ -6,12 +6,26 @@ package auction import ( "fmt" + "encoding/base64" "github.com/hyperledger/fabric-chaincode-go/pkg/statebased" "github.com/hyperledger/fabric-chaincode-go/shim" "github.com/hyperledger/fabric-contract-api-go/contractapi" ) +func (s *SmartContract) GetSubmittingClientIdentity(ctx contractapi.TransactionContextInterface) (string, error) { + + b64ID, err := ctx.GetClientIdentity().GetID() + if err != nil { + return "", fmt.Errorf("Failed to read clientID: %v", err) + } + decodeID, err := base64.StdEncoding.DecodeString(b64ID) + if err != nil { + return "", fmt.Errorf("failed to base64 decode clientID: %v", err) + } + return string(decodeID), nil +} + // setAssetStateBasedEndorsement sets the endorsement policy of a new auction func setAssetStateBasedEndorsement(ctx contractapi.TransactionContextInterface, auctionID string, orgToEndorse string) error {