Move off chain data samples to basic chaincode

Signed-off-by: NIKHIL E GUPTA <ngupta@symbridge.com>
This commit is contained in:
NIKHIL E GUPTA 2020-09-17 12:45:54 -04:00 committed by denyeart
parent 327e3a78aa
commit 6d196bd9df
8 changed files with 189 additions and 382 deletions

View file

@ -10,9 +10,9 @@ CouchDB.
## Getting started
This sample uses Node Fabric SDK application code similar to the `fabcar` sample
to connect to a running instance of the Fabric test network. Make sure that you
are running the following commands from the `off_chain_data` directory.
This sample uses Node Fabric SDK application code to connect to a running instance
of the Fabric test network. Make sure that you are running the following
commands from the `off_chain_data` directory.
### Starting the Network
@ -25,7 +25,8 @@ Use the following command to start the sample network:
This command will deploy an instance of the Fabric test network. The network
consists of an ordering service, two peer organizations with one peers each, and
a CA for each org. The command also creates a channel named `mychannel`. The
marbles chaincode will be installed on both peers and deployed to the channel.
`asset-transfer-basic` chaincode will be installed on both peers and deployed to
the channel.
### Configuration
@ -55,10 +56,11 @@ If you set the "use_couchdb" option to true in `config.json`, you can run the
following command start a local instance of CouchDB using docker:
```
docker run --publish 5990:5984 --detach --name offchaindb couchdb
docker run --publish 5990:5984 --detach --name offchaindb couchdb:2.3.1
docker start offchaindb
```
### Install dependencies
You need to install Node.js version 8.9.x to use the sample application code.
@ -92,53 +94,7 @@ node blockEventListener.js
If the command is successful, you should see the output of the listener reading
the configuration blocks of `mychannel` in addition to the blocks that recorded
the approval and commitment of the marbles chaincode definition.
```
Listening for block events, nextblock: 0
Added block 0 to ProcessingMap
Added block 1 to ProcessingMap
Added block 2 to ProcessingMap
Added block 3 to ProcessingMap
Added block 4 to ProcessingMap
Added block 5 to ProcessingMap
Added block 6 to ProcessingMap
------------------------------------------------
Block Number: 0
------------------------------------------------
Block Number: 1
------------------------------------------------
Block Number: 2
------------------------------------------------
Block Number: 3
Block Timestamp: 2019-08-08T19:47:56.148Z
ChaincodeID: _lifecycle
[]
------------------------------------------------
Block Number: 4
Block Timestamp: 2019-08-08T19:48:00.234Z
ChaincodeID: _lifecycle
[]
------------------------------------------------
Block Number: 5
Block Timestamp: 2019-08-08T19:48:14.092Z
ChaincodeID: _lifecycle
[ { key: 'namespaces/fields/marbles/Collections',
is_delete: false,
value: '\u0012\u0000' },
{ key: 'namespaces/fields/marbles/EndorsementInfo',
is_delete: false,
value: '\u0012\r\n\u00031.0\u0010\u0001\u001a\u0004escc' },
{ key: 'namespaces/fields/marbles/Sequence',
is_delete: false,
value: '\b\u0001' },
{ key: 'namespaces/fields/marbles/ValidationInfo',
is_delete: false,
value: '\u00122\n\u0004vscc\u0012*\n(\u0012\f\u0012\n\b\u0002\u0012\u0002\b\u0000\u0012\u0002\b\u0001\u001a\u000b\u0012\t\n\u0007Org1MSP\u001a\u000b\u0012\t\n\u0007Org2MSP' },
{ key: 'namespaces/metadata/marbles',
is_delete: false,
value: '\n\u0013ChaincodeDefinition\u0012\bSequence\u0012\u000fEndorsementInfo\u0012\u000eValidationInfo\u0012\u000bCollections' } ]
```
the approval and commitment of the assets chaincode definition.
`blockEventListener.js` creates a listener named "offchain-listener" on the
channel `mychannel`. The listener writes each block added to the channel to a
@ -157,7 +113,7 @@ read-write set.
The channel event listener also writes metadata from each block to a log file
defined as channelid_chaincodeid.log. In this example, events will be written to
a file named `mychannel_marbles.log`. This allows you to record a history of
a file named `mychannel_basic.log`. This allows you to record a history of
changes made by each block for each key in addition to storing the latest value
of the world state.
@ -166,42 +122,42 @@ new window to execute the next parts of the demo.
### Generate data on the blockchain
Now that our listener is setup, we can generate data using the marbles chaincode
Now that our listener is setup, we can generate data using the assets chaincode
and use our application to replicate the data to our database. Open a new
terminal and navigate to the `fabric-samples/off_chain_data` directory.
You can use the `addMarbles.js` file to add random sample data to blockchain.
The file uses the configuration information stored in `addMarbles.json` to
create a series of marbles. This file will be created during the first execution
of `addMarbles.js` if it does not exist. This program can be run multiple times
without changing the properties. The `nextMarbleNumber` will be incremented and
stored in the `addMarbles.json` file.
You can use the `addAssets.js` file to add random sample data to blockchain.
The file uses the configuration information stored in `addAssets.json` to
create a series of assets. This file will be created during the first execution
of `addAssets.js` if it does not exist. This program can be run multiple times
without changing the properties. The `nextAssetNumber` will be incremented and
stored in the `addAssets.json` file.
```
{
"nextMarbleNumber": 100,
"numberMarblesToAdd": 20
"nextAssetNumber": 100,
"numberAssetsToAdd": 20
}
```
Open a new window and run the following command to add 20 marbles to the
Open a new window and run the following command to add 20 assets to the
blockchain:
```
node addMarbles.js
node addAssets.js
```
After the marbles have been added to the ledger, use the following command to
transfer one of the marbles to a new owner:
After the assets have been added to the ledger, use the following command to
transfer one of the assets to a new owner:
```
node transferMarble.js marble110 james
node transferAsset.js asset110 james
```
Now run the following command to delete the marble that was transferred:
Now run the following command to delete the asset that was transferred:
```
node deleteMarble.js marble110
node deleteAsset.js asset110
```
## Offchain CouchDB storage:
@ -215,17 +171,17 @@ The first table is an offline representation of the current world state of the
blockchain ledger. This table was created using the read-write set data from
the blocks. If the listener is running, this table should be the same as the
latest values in the state database running on your peer. The table is named
after the channelid and chaincodeid, and is named mychannel_marbles in this
after the channelid and chaincodeid, and is named mychannel_basic in this
example. You can navigate to this table using your browser:
http://127.0.0.1:5990/mychannel_marbles/_all_docs
http://127.0.0.1:5990/mychannel_basic/_all_docs
A second table records each block as a historical record entry, and was created
using the block data that was recorded in the log file. The table name appends
history to the name of the first table, and is named mychannel_marbles_history
history to the name of the first table, and is named mychannel_basic_history
in this example. You can also navigate to this table using your browser:
http://127.0.0.1:5990/mychannel_marbles_history/_all_docs
http://127.0.0.1:5990/mychannel_basic_history/_all_docs
### Configure a map/reduce view for summarizing counts of marbles by color:
### Configure a map/reduce view for summarizing counts of assets by color:
Now that we have state and history data replicated to tables in CouchDB, we
can use the following commands query our off-chain data. We will also add an
@ -236,16 +192,16 @@ created when events are received.
Open a new terminal window and execute the following:
```
curl -X PUT http://127.0.0.1:5990/mychannel_marbles/_design/colorviewdesign -d '{"views":{"colorview":{"map":"function (doc) { emit(doc.color, 1);}","reduce":"function ( keys , values , combine ) {return sum( values )}"}}}' -H 'Content-Type:application/json'
curl -X PUT http://127.0.0.1:5990/mychannel_basic/_design/colorviewdesign -d '{"views":{"colorview":{"map":"function (doc) { emit(doc.color, 1);}","reduce":"function ( keys , values , combine ) {return sum( values )}"}}}' -H 'Content-Type:application/json'
```
Execute a query to retrieve the total number of marbles (reduce function):
Execute a query to retrieve the total number of assets (reduce function):
```
curl -X GET http://127.0.0.1:5990/mychannel_marbles/_design/colorviewdesign/_view/colorview?reduce=true
curl -X GET http://127.0.0.1:5990/mychannel_basic/_design/colorviewdesign/_view/colorview?reduce=true
```
If successful, this command will return the number of marbles in the blockchain
If successful, this command will return the number of assets in the blockchain
world state, without having to query the blockchain ledger:
```
@ -254,13 +210,13 @@ world state, without having to query the blockchain ledger:
]}
```
Execute a new query to retrieve the number of marbles by color (map function):
Execute a new query to retrieve the number of assets by color (map function):
```
curl -X GET http://127.0.0.1:5990/mychannel_marbles/_design/colorviewdesign/_view/colorview?group=true
curl -X GET http://127.0.0.1:5990/mychannel_basic/_design/colorviewdesign/_view/colorview?group=true
```
The command will return a list of marbles by color from the CouchDB database.
The command will return a list of assets by color from the CouchDB database.
```
{"rows":[
@ -275,27 +231,27 @@ The command will return a list of marbles by color from the CouchDB database.
To run a more complex command that reads through the block history database, we
will create an index of the blocknumber, sequence, and key fields. This index
will support a query that traces the history of each marble. Execute the
will support a query that traces the history of each asset. Execute the
following command to create the index:
```
curl -X POST http://127.0.0.1:5990/mychannel_marbles_history/_index -d '{"index":{"fields":["blocknumber", "sequence", "key"]},"name":"marble_history"}' -H 'Content-Type:application/json'
curl -X POST http://127.0.0.1:5990/mychannel_basic_history/_index -d '{"index":{"fields":["blocknumber", "sequence", "key"]},"name":"asset_history"}' -H 'Content-Type:application/json'
```
Now execute a query to retrieve the history for the marble we transferred and
Now execute a query to retrieve the history for the asset we transferred and
then deleted:
```
curl -X POST http://127.0.0.1:5990/mychannel_marbles_history/_find -d '{"selector":{"key":{"$eq":"marble110"}}, "fields":["blocknumber","is_delete","value"],"sort":[{"blocknumber":"asc"}, {"sequence":"asc"}]}' -H 'Content-Type:application/json'
curl -X POST http://127.0.0.1:5990/mychannel_basic_history/_find -d '{"selector":{"key":{"$eq":"asset110"}}, "fields":["blocknumber","is_delete","value"],"sort":[{"blocknumber":"asc"}, {"sequence":"asc"}]}' -H 'Content-Type:application/json'
```
You should see the transaction history of the marble that was created,
You should see the transaction history of the asset that was created,
transferred, and then removed from the ledger.
```
{"docs":[
{"blocknumber":12,"is_delete":false,"value":"{\"docType\":\"marble\",\"name\":\"marble110\",\"color\":\"blue\",\"size\":60,\"owner\":\"debra\"}"},
{"blocknumber":22,"is_delete":false,"value":"{\"docType\":\"marble\",\"name\":\"marble110\",\"color\":\"blue\",\"size\":60,\"owner\":\"james\"}"},
{"blocknumber":12,"is_delete":false,"value":"{\"docType\":\"asset\",\"name\":\"asset110\",\"color\":\"blue\",\"size\":60,\"owner\":\"debra\"}"},
{"blocknumber":22,"is_delete":false,"value":"{\"docType\":\"asset\",\"name\":\"asset110\",\"color\":\"blue\",\"size\":60,\"owner\":\"james\"}"},
{"blocknumber":23,"is_delete":true,"value":""}
]}
```
@ -309,19 +265,19 @@ have missed.
If you ran through the example steps above, navigate back to the terminal window
where `blockEventListener.js` is running and close it. Once the listener is no
longer running, use the following command to add 20 more marbles to the
longer running, use the following command to add 20 more assets to the
ledger:
```
node addMarbles.js
node addAssets.js
```
The listener will not be able to add the new marbles to your CouchDB database.
The listener will not be able to add the new assets to your CouchDB database.
If you check the current state table using the reduce command, you will only
be able to see the original marbles in your database.
be able to see the original assets in your database.
```
curl -X GET http://127.0.0.1:5990/mychannel_marbles/_design/colorviewdesign/_view/colorview?reduce=true
curl -X GET http://127.0.0.1:5990/mychannel_basic/_design/colorviewdesign/_view/colorview?reduce=true
```
To add the new data to your off-chain database, remove the `nextblock.txt`
@ -337,15 +293,15 @@ You can new re-run the channel listener to read every block from the channel:
node blockEventListener.js
```
This will rebuild the CouchDB tables and include the 20 marbles that have been
This will rebuild the CouchDB tables and include the 20 assets that have been
added to the ledger. If you run the reduce command against your database one
more time,
```
curl -X GET http://127.0.0.1:5990/mychannel_marbles/_design/colorviewdesign/_view/colorview?reduce=true
curl -X GET http://127.0.0.1:5990/mychannel_basic/_design/colorviewdesign/_view/colorview?reduce=true
```
you will be able to see that all of the marbles have been added to your
you will be able to see that all of the assets have been added to your
database:
```
@ -369,4 +325,4 @@ Running the script will complete the following actions:
* Remove the certificates you generated by deleting the `wallet` folder.
* Delete `nextblock.txt` so you can start with the first block next time you
operate the listener.
* Removes `addMarbles.json`.
* Removes `addAssets.json`.

118
off_chain_data/addAssets.js Normal file
View file

@ -0,0 +1,118 @@
/*
* Copyright IBM Corp. All Rights Reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
*/
/*
*
* addAssets.js will add random sample data to blockchain.
*
* $ node addAssets.js
*
* addAssets will add 10 Assets by default with a starting Asset name of "Asset100".
* Additional Assets will be added by incrementing the number at the end of the Asset name.
*
* The properties for adding Assets are stored in addAssets.json. This file will be created
* during the first execution of the utility if it does not exist. The utility can be run
* multiple times without changing the properties. The nextAssetNumber will be incremented and
* stored in the JSON file.
*
* {
* "nextAssetNumber": 100,
* "numberAssetsToAdd": 10
* }
*
*/
'use strict';
const { Wallets, Gateway } = require('fabric-network');
const fs = require('fs');
const path = require('path');
const addAssetsConfigFile = path.resolve(__dirname, 'addAssets.json');
const colors=[ 'blue', 'red', 'yellow', 'green', 'white', 'purple' ];
const owners=[ 'tom', 'fred', 'julie', 'james', 'janet', 'henry', 'alice', 'marie', 'sam', 'debra', 'nancy'];
const sizes=[ 10, 20, 30, 40, 50, 60, 70, 80, 90, 100 ];
const appraisedValues=[ 300, 310, 320, 330, 340, 350, 360, 370, 380, 390 ];
const docType='asset'
const config = require('./config.json');
const channelid = config.channelid;
async function main() {
try {
let nextAssetNumber;
let numberAssetsToAdd;
let addAssetsConfig;
// check to see if there is a config json defined
if (fs.existsSync(addAssetsConfigFile)) {
// read file the next asset and number of assets to create
let addAssetsConfigJSON = fs.readFileSync(addAssetsConfigFile, 'utf8');
addAssetsConfig = JSON.parse(addAssetsConfigJSON);
nextAssetNumber = addAssetsConfig.nextAssetNumber;
numberAssetsToAdd = addAssetsConfig.numberAssetsToAdd;
} else {
nextAssetNumber = 100;
numberAssetsToAdd = 20;
// create a default config and save
addAssetsConfig = new Object;
addAssetsConfig.nextAssetNumber = nextAssetNumber;
addAssetsConfig.numberAssetsToAdd = numberAssetsToAdd;
fs.writeFileSync(addAssetsConfigFile, JSON.stringify(addAssetsConfig, null, 2));
}
// Parse the connection profile.
const ccpPath = path.resolve(__dirname, '..', 'test-network','organizations','peerOrganizations','org1.example.com', 'connection-org1.json');
const ccp = JSON.parse(fs.readFileSync(ccpPath, 'utf8'));
// Configure a wallet. This wallet must already be primed with an identity that
// the application can use to interact with the peer node.
const walletPath = path.resolve(__dirname, 'wallet');
const wallet = await Wallets.newFileSystemWallet(walletPath);
// Create a new gateway, and connect to the gateway peer node(s). The identity
// specified must already exist in the specified wallet.
const gateway = new Gateway();
await gateway.connect(ccp, { wallet, identity: 'appUser', discovery: { enabled: true, asLocalhost: true } });
// Get the network channel that the smart contract is deployed to.
const network = await gateway.getNetwork(channelid);
// Get the smart contract from the network channel.
const contract = network.getContract('basic');
for (var counter = nextAssetNumber; counter < nextAssetNumber + numberAssetsToAdd; counter++) {
var randomColor = Math.floor(Math.random() * (6));
var randomOwner = Math.floor(Math.random() * (11));
var randomSize = Math.floor(Math.random() * (10));
var randomValue = Math.floor(Math.random() * (9));
// Submit the 'CreateAsset' transaction to the smart contract, and wait for it
// to be committed to the ledger.
await contract.submitTransaction('CreateAsset', docType+counter, colors[randomColor], ''+sizes[randomSize], owners[randomOwner],appraisedValues[randomValue]);
console.log("Adding asset: " + docType + counter + " owner:" + owners[randomOwner] + " color:" + colors[randomColor] + " size:" + '' + sizes[randomSize] + " appraised value:" + '' + appraisedValues[randomValue] );
}
await gateway.disconnect();
addAssetsConfig.nextAssetNumber = nextAssetNumber + numberAssetsToAdd;
fs.writeFileSync(addAssetsConfigFile, JSON.stringify(addAssetsConfig, null, 2));
} catch (error) {
console.error(`Failed to submit transaction: ${error}`);
process.exit(1);
}
}
main();

View file

@ -1,117 +0,0 @@
/*
* Copyright IBM Corp. All Rights Reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
*/
/*
*
* addMarbles.js will add random sample data to blockchain.
*
* $ node addMarbles.js
*
* addMarbles will add 10 marbles by default with a starting marble name of "marble100".
* Additional marbles will be added by incrementing the number at the end of the marble name.
*
* The properties for adding marbles are stored in addMarbles.json. This file will be created
* during the first execution of the utility if it does not exist. The utility can be run
* multiple times without changing the properties. The nextMarbleNumber will be incremented and
* stored in the JSON file.
*
* {
* "nextMarbleNumber": 100,
* "numberMarblesToAdd": 10
* }
*
*/
'use strict';
const { Wallets, Gateway } = require('fabric-network');
const fs = require('fs');
const path = require('path');
const addMarblesConfigFile = path.resolve(__dirname, 'addMarbles.json');
const colors=[ 'blue', 'red', 'yellow', 'green', 'white', 'purple' ];
const owners=[ 'tom', 'fred', 'julie', 'james', 'janet', 'henry', 'alice', 'marie', 'sam', 'debra', 'nancy'];
const sizes=[ 10, 20, 30, 40, 50, 60, 70, 80, 90, 100 ];
const docType='marble'
const config = require('./config.json');
const channelid = config.channelid;
async function main() {
try {
let nextMarbleNumber;
let numberMarblesToAdd;
let addMarblesConfig;
// check to see if there is a config json defined
if (fs.existsSync(addMarblesConfigFile)) {
// read file the next marble and number of marbles to create
let addMarblesConfigJSON = fs.readFileSync(addMarblesConfigFile, 'utf8');
addMarblesConfig = JSON.parse(addMarblesConfigJSON);
nextMarbleNumber = addMarblesConfig.nextMarbleNumber;
numberMarblesToAdd = addMarblesConfig.numberMarblesToAdd;
} else {
nextMarbleNumber = 100;
numberMarblesToAdd = 20;
// create a default config and save
addMarblesConfig = new Object;
addMarblesConfig.nextMarbleNumber = nextMarbleNumber;
addMarblesConfig.numberMarblesToAdd = numberMarblesToAdd;
fs.writeFileSync(addMarblesConfigFile, JSON.stringify(addMarblesConfig, null, 2));
}
// Parse the connection profile. This would be the path to the file downloaded
// from the IBM Blockchain Platform operational console.
const ccpPath = path.resolve(__dirname, '..', 'test-network','organizations','peerOrganizations','org1.example.com', 'connection-org1.json');
const ccp = JSON.parse(fs.readFileSync(ccpPath, 'utf8'));
// Configure a wallet. This wallet must already be primed with an identity that
// the application can use to interact with the peer node.
const walletPath = path.resolve(__dirname, 'wallet');
const wallet = await Wallets.newFileSystemWallet(walletPath);
// Create a new gateway, and connect to the gateway peer node(s). The identity
// specified must already exist in the specified wallet.
const gateway = new Gateway();
await gateway.connect(ccp, { wallet, identity: 'appUser', discovery: { enabled: true, asLocalhost: true } });
// Get the network channel that the smart contract is deployed to.
const network = await gateway.getNetwork(channelid);
// Get the smart contract from the network channel.
const contract = network.getContract('marbles');
for (var counter = nextMarbleNumber; counter < nextMarbleNumber + numberMarblesToAdd; counter++) {
var randomColor = Math.floor(Math.random() * (6));
var randomOwner = Math.floor(Math.random() * (11));
var randomSize = Math.floor(Math.random() * (10));
// Submit the 'initMarble' transaction to the smart contract, and wait for it
// to be committed to the ledger.
await contract.submitTransaction('initMarble', docType+counter, colors[randomColor], ''+sizes[randomSize], owners[randomOwner]);
console.log("Adding marble: " + docType + counter + " owner:" + owners[randomOwner] + " color:" + colors[randomColor] + " size:" + '' + sizes[randomSize] );
}
await gateway.disconnect();
addMarblesConfig.nextMarbleNumber = nextMarbleNumber + numberMarblesToAdd;
fs.writeFileSync(addMarblesConfigFile, JSON.stringify(addMarblesConfig, null, 2));
} catch (error) {
console.error(`Failed to submit transaction: ${error}`);
process.exit(1);
}
}
main();

View file

@ -7,9 +7,9 @@
/*
*
* deleteMarble.js will delete a specified marble. Example:
* deleteAsset.js will delete a specified asset. Example:
*
* $ node deleteMarble.js marble100
* $ node deleteAsset.js asset100
*
* The utility is meant to demonstrate delete block events.
*/
@ -26,7 +26,7 @@ const channelid = config.channelid;
async function main() {
if (process.argv[2] == undefined) {
console.log("Usage: node deleteMarble marbleId");
console.log("Usage: node deleteAsset AssetId");
process.exit(1);
}
@ -34,8 +34,7 @@ async function main() {
try {
// Parse the connection profile. This would be the path to the file downloaded
// from the IBM Blockchain Platform operational console.
// Parse the connection profile.
const ccpPath = path.resolve(__dirname, '..', 'test-network','organizations','peerOrganizations','org1.example.com', 'connection-org1.json');
const ccp = JSON.parse(fs.readFileSync(ccpPath, 'utf8'));
@ -53,10 +52,10 @@ async function main() {
const network = await gateway.getNetwork(channelid);
// Get the smart contract from the network channel.
const contract = network.getContract('marbles');
const contract = network.getContract('basic');
await contract.submitTransaction('delete', deletekey);
console.log("Deleted marble: " + deletekey);
await contract.submitTransaction('DeleteAsset', deletekey);
console.log("Deleted asset: " + deletekey);
await gateway.disconnect();

View file

@ -14,7 +14,7 @@ popd
# clean out any old identites in the wallets
rm -rf wallet
rm -rf addMarbles.json mychannel_marbles.log mychannel__lifecycle.log nextblock.txt
rm -rf addAssets.json mychannel_basic.log mychannel__lifecycle.log nextblock.txt
docker stop offchaindb
docker rm offchaindb

View file

@ -15,8 +15,8 @@
"author": "Hyperledger",
"license": "Apache-2.0",
"dependencies": {
"fabric-ca-client": "^2.1.0",
"fabric-network": "^2.1.0"
"fabric-ca-client": "^2.2.0",
"fabric-network": "^2.2.0"
},
"devDependencies": {
"chai": "^4.2.0",

View file

@ -7,161 +7,13 @@
# Exit on first error
set -e pipefail
# don't rewrite paths for Windows Git Bash users
export MSYS_NO_PATHCONV=1
starttime=$(date +%s)
CC_SRC_LANGUAGE=golang
CC_RUNTIME_LANGUAGE=golang
CC_SRC_PATH=../chaincode/marbles02/go
echo Vendoring Go dependencies ...
pushd ../chaincode/marbles02/go
GO111MODULE=on go mod vendor
popd
echo Finished vendoring Go dependencies
# launch network; create channel and join peer to channel
pushd ../test-network
./network.sh down
./network.sh up createChannel -ca -s couchdb
export PATH=${PWD}/../bin:${PWD}:$PATH
export FABRIC_CFG_PATH=${PWD}/../config
# import environment variables
. scripts/envVar.sh
echo "Packaging the marbles smart contract"
setGlobals 1
peer lifecycle chaincode package marbles.tar.gz \
--path $CC_SRC_PATH \
--lang $CC_RUNTIME_LANGUAGE \
--label marblesv1
echo "Installing smart contract on peer0.org1.example.com"
peer lifecycle chaincode install marbles.tar.gz
echo "Installing smart contract on peer0.org2.example.com"
setGlobals 2
peer lifecycle chaincode install marbles.tar.gz
echo "Query the chaincode package id"
setGlobals 1
peer lifecycle chaincode queryinstalled >&log.txt
PACKAGE_ID=$(sed -n "/marblesv1/{s/^Package ID: //; s/, Label:.*$//; p;}" log.txt)
echo "Approving the chaincode definition for org1.example.com"
peer lifecycle chaincode approveformyorg \
-o localhost:7050 \
--ordererTLSHostnameOverride orderer.example.com \
--channelID mychannel \
--name marbles \
--version 1.0 \
--init-required \
--signature-policy AND"('Org1MSP.member','Org2MSP.member')" \
--sequence 1 \
--package-id $PACKAGE_ID \
--tls \
--cafile ${ORDERER_CA}
echo "Approving the chaincode definition for org2.example.com"
setGlobals 2
peer lifecycle chaincode approveformyorg \
-o localhost:7050 \
--ordererTLSHostnameOverride orderer.example.com \
--channelID mychannel \
--name marbles \
--version 1.0 \
--init-required \
--signature-policy AND"('Org1MSP.member','Org2MSP.member')" \
--sequence 1 \
--package-id $PACKAGE_ID \
--tls \
--cafile ${ORDERER_CA}
echo "Checking if the chaincode definition is ready to commit"
peer lifecycle chaincode checkcommitreadiness \
--channelID mychannel \
--name marbles \
--version 1.0 \
--sequence 1 \
--output json \
--init-required \
--signature-policy AND"('Org1MSP.member','Org2MSP.member')" >&log.txt
rc=0
for var in "\"Org1MSP\": true" "\"Org2MSP\": true"
do
grep "$var" log.txt &>/dev/null || let rc=1
done
if test $rc -eq 0; then
echo "Chaincode definition is ready to commit"
else
sleep 10
fi
parsePeerConnectionParameters 1 2
echo "Commit the chaincode definition to the channel"
peer lifecycle chaincode commit \
-o localhost:7050 \
--ordererTLSHostnameOverride orderer.example.com \
--channelID mychannel \
--name marbles \
--version 1.0 \
--init-required \
--signature-policy AND"('Org1MSP.member','Org2MSP.member')" \
--sequence 1 \
--tls \
--cafile ${ORDERER_CA} \
$PEER_CONN_PARMS
echo "Check if the chaincode has been committed to the channel ..."
peer lifecycle chaincode querycommitted \
--channelID mychannel \
--name marbles >&log.txt
EXPECTED_RESULT="Version: 1.0, Sequence: 1, Endorsement Plugin: escc, Validation Plugin: vscc"
VALUE=$(grep -o "Version: 1.0, Sequence: 1, Endorsement Plugin: escc, Validation Plugin: vscc" log.txt)
echo "$VALUE"
if [ "$VALUE" = "Version: 1.0, Sequence: 1, Endorsement Plugin: escc, Validation Plugin: vscc" ] ; then
echo "chaincode has been committed"
else
sleep 10
fi
echo "invoke the marbles chaincode init function ... "
peer chaincode invoke \
-o localhost:7050 \
--ordererTLSHostnameOverride orderer.example.com \
-C mychannel \
-n marbles \
--isInit \
-c '{"Args":["Init"]}' \
--tls \
--cafile ${ORDERER_CA} \
$PEER_CONN_PARMS
rm log.txt
./network.sh deployCC
popd

View file

@ -6,9 +6,9 @@
*/
/*
* tranferMarble.js will transfer ownership a specified marble to a new ownder. Example:
* tranferAsset.js will transfer ownership a specified asset to a new ownder. Example:
*
* $ node transferMarble.js marble102 jimmy
* $ node transferAsset.js asset102 jimmy
*
* The utility is meant to demonstrate update block events.
*/
@ -25,7 +25,7 @@ const channelid = config.channelid;
async function main() {
if (process.argv[2] == undefined && process.argv[3] == undefined) {
console.log("Usage: node changeMarbleOwner.js marbleId owner");
console.log("Usage: node transferAsset.js assetId owner");
process.exit(1);
}
@ -34,8 +34,7 @@ async function main() {
try {
// Parse the connection profile. This would be the path to the file downloaded
// from the IBM Blockchain Platform operational console.
// Parse the connection profile.
const ccpPath = path.resolve(__dirname, '..', 'test-network','organizations','peerOrganizations','org1.example.com', 'connection-org1.json');
const ccp = JSON.parse(fs.readFileSync(ccpPath, 'utf8'));
@ -53,10 +52,10 @@ async function main() {
const network = await gateway.getNetwork(channelid);
// Get the smart contract from the network channel.
const contract = network.getContract('marbles');
const contract = network.getContract('basic');
await contract.submitTransaction('transferMarble', updatekey, newowner);
console.log("Transferred marble " + updatekey + " to " + newowner);
await contract.submitTransaction('TransferAsset', updatekey, newowner);
console.log("Transferred asset " + updatekey + " to " + newowner);
await gateway.disconnect();