Auction sample clean up (#408)

Signed-off-by: Nikhil Gupta <ngupta@symbridge.com>

Co-authored-by: Nikhil Gupta <nikhilgupta@macbook-air.lan>
This commit is contained in:
nikhil550 2021-02-01 04:19:45 -05:00 committed by GitHub
parent 822c4c4c25
commit 7b1168cd9d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
13 changed files with 146 additions and 276 deletions

View file

@ -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"
}

View file

@ -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();

View file

@ -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];

View file

@ -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];

View file

@ -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];

View file

@ -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();

View file

@ -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];

View file

@ -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];

View file

@ -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();

View file

@ -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];

View file

@ -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
}

View file

@ -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()

View file

@ -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 {