From 75e293183b8f2ccd608d49c5cdcf628b49ee133f Mon Sep 17 00:00:00 2001 From: Keith Smith Date: Fri, 22 Jun 2018 09:25:05 -0400 Subject: [PATCH 01/35] [FAB-10811] fabric-ca sample is broken on v1.2 The Profile section of configtx.yaml must now be at the end of the file, so the building of this file dynamically must be updated. I also updated the version of the fabric CA in bootstrap.sh to 1.2.0. Change-Id: Ifabccebc901f74569cfa1fe1d824fbcd26c4ffd1 Signed-off-by: Keith Smith Signed-off-by: Christopher Ferris --- fabric-ca/README.md | 52 +++++++++++----------- fabric-ca/bootstrap.sh | 10 +---- fabric-ca/scripts/setup-fabric.sh | 72 +++++++++++++++---------------- scripts/bootstrap.sh | 4 +- 4 files changed, 66 insertions(+), 72 deletions(-) diff --git a/fabric-ca/README.md b/fabric-ca/README.md index 9c11e16f..d704faa9 100755 --- a/fabric-ca/README.md +++ b/fabric-ca/README.md @@ -5,50 +5,50 @@ The Hyperledger Fabric CA sample demonstrates the following: * How to use the Hyperledger Fabric CA client and server to generate all crypto material rather than using cryptogen. The cryptogen tool is not intended for a production environment because it generates all private keys in one location - which must then be copied to the appropriate host or container. This sample demonstrates - how to generate crypto material for orderers, peers, administrators, and end - users so that private keys never leave the host or container in which they are generated. + which must then be copied to the appropriate host or container. This sample + demonstrates how to generate crypto material for orderers, peers, + administrators, and end users so that private keys never leave the host or + container in which they are generated. -* How to use Attribute-Based Access Control (ABAC). See fabric-samples/chaincode/abac/abac.go and - note the use of the *github.com/hyperledger/fabric/core/chaincode/lib/cid* package to extract - attributes from the invoker's identity. Only identities with the *abac.init* attribute value of - *true* can successfully call the *Init* function to instantiate the chaincode. +* How to use Attribute-Based Access Control (ABAC). See + fabric-samples/chaincode/abac/abac.go and note the use of the *github.com/hyperledger/fabric/core/chaincode/lib/cid* package to extract + attributes from the invoker's identity. Only identities with the *abac.init* + attribute value of *true* can successfully call the *Init* function to + instantiate the chaincode. ## Running this sample 1. The following images are required to run this sample: *hyperledger/fabric-ca-orderer*, *hyperledger/fabric-ca-peer*, and *hyperledger/fabric-ca-tools* - #### 1.1.0 - Run the *bootstrap.sh* script provided with this sample to download the required images for - fabric-ca sample. + #### install the images + Run the *bootstrap.sh* script provided with this sample to download the + required images for fabric-ca sample. For the v1.2.0-rc1 release, you + will need to specify the version as follows: - #### 1.0.X - These images are new in the v1.1.0 release of the *github.com/hyperledger/fabric-ca*. - In order to run this sample prior to the v1.1.0 release, you must build these - images manually as follows: - a) pull the master branch of the *github.com/hyperledger/fabric* and - *github.com/hyperledger/fabric-ca* repositories; - b) make sure these repositories are on your GOPATH; - c) run the *build-images.sh* script provided with this sample. + ``` + bootstrap.sh 1.2.0-rc1 + ``` -2. To run this sample, simply run the *start.sh* script. You may do this multiple times in a row as needed -since the *start.sh* script cleans up before starting each time. +2. To run this sample, simply run the *start.sh* script. You may do this +multiple times in a row as needed since the *start.sh* script cleans up before +starting each time. 3. To stop the containers which are started by the *start.sh* script, you may run the *stop.sh* script. ## Understanding this sample -There are some variables at the top of *fabric-samples/fabric-ca/scripts/env.sh* script which -define the names and topology of this sample. You may modify these as described in the comments -of the script in order to customize this sample. By default, there are three organizations. -The orderer organization is *org0*, and two peer organizations are *org1* and *org2*. +There are some variables at the top of *fabric-samples/fabric-ca/scripts/env.sh* +script which define the names and topology of this sample. You may modify these +as described in the comments of the script in order to customize this sample. +By default, there are three organizations. The orderer organization is *org0*, +and two peer organizations are *org1* and *org2*. The *start.sh* script first builds the *docker-compose.yml* file (by invoking the *makeDocker.sh* script) and then starts the docker containers. The *data* directory is a volume mount for all containers. -This volume mount is not be needed in a real scenario, but it is used by this sample -for the following reasons: +This volume mount is not be needed in a real scenario, but it is used by this +sample for the following reasons: a) so that all containers can write their logs to a common directory (i.e. *the *data/logs* directory) to make debugging easier; b) to synchronize the sequence in which containers start as described below diff --git a/fabric-ca/bootstrap.sh b/fabric-ca/bootstrap.sh index f536c16a..ad096e24 100755 --- a/fabric-ca/bootstrap.sh +++ b/fabric-ca/bootstrap.sh @@ -6,13 +6,9 @@ # # current version of fabric-ca released -export CA_VERSION=${1:-1.1.0} -export ARCH=$(echo "$(uname -s|tr '[:upper:]' '[:lower:]'|sed 's/mingw64_nt.*/windows/')-$(uname -m | sed 's/x86_64/amd64/g')" | awk '{print tolower($0)}') -#Set MARCH variable i.e ppc64le,s390x,x86_64,i386 -MARCH=`uname -m` +export CA_TAG=${1:-1.2.0} dockerCaPull() { - local CA_TAG=$1 echo "==> FABRIC CA IMAGE" echo for image in "" "-tools" "-orderer" "-peer"; do @@ -21,10 +17,8 @@ dockerCaPull() { done } -: ${CA_TAG:="$MARCH-$CA_VERSION"} - echo "===> Pulling fabric ca Image" dockerCaPull ${CA_TAG} echo "===> List out hyperledger docker images" -docker images | grep hyperledger* +docker images | grep hyperledger/fabric-ca diff --git a/fabric-ca/scripts/setup-fabric.sh b/fabric-ca/scripts/setup-fabric.sh index 90beeb80..48c3c57a 100755 --- a/fabric-ca/scripts/setup-fabric.sh +++ b/fabric-ca/scripts/setup-fabric.sh @@ -124,7 +124,42 @@ function printPeerOrg { function makeConfigTxYaml { { - echo "################################################################################ + echo " +################################################################################ +# +# Section: Organizations +# +# - This section defines the different organizational identities which will +# be referenced later in the configuration. +# +################################################################################ +Organizations:" + + for ORG in $ORDERER_ORGS; do + printOrdererOrg $ORG + done + + for ORG in $PEER_ORGS; do + printPeerOrg $ORG 1 + done + + echo " +################################################################################ +# +# SECTION: Application +# +# This section defines the values to encode into a config transaction or +# genesis block for application related parameters +# +################################################################################ +Application: &ApplicationDefaults + + # Organizations is the list of orgs which are defined as participants on + # the application side of the network + Organizations: +" + echo " +################################################################################ # # Profile # @@ -208,41 +243,6 @@ Profiles: echo " - *${ORG_CONTAINER_NAME}" done - echo " -################################################################################ -# -# Section: Organizations -# -# - This section defines the different organizational identities which will -# be referenced later in the configuration. -# -################################################################################ -Organizations:" - - for ORG in $ORDERER_ORGS; do - printOrdererOrg $ORG - done - - for ORG in $PEER_ORGS; do - printPeerOrg $ORG 1 - done - - echo " -################################################################################ -# -# SECTION: Application -# -# This section defines the values to encode into a config transaction or -# genesis block for application related parameters -# -################################################################################ -Application: &ApplicationDefaults - - # Organizations is the list of orgs which are defined as participants on - # the application side of the network - Organizations: -" - } > /etc/hyperledger/fabric/configtx.yaml # Copy it to the data directory to make debugging easier cp /etc/hyperledger/fabric/configtx.yaml /$DATA diff --git a/scripts/bootstrap.sh b/scripts/bootstrap.sh index 37beaf4d..b02d9004 100755 --- a/scripts/bootstrap.sh +++ b/scripts/bootstrap.sh @@ -6,11 +6,11 @@ # # if version not passed in, default to latest released version -export VERSION=1.1.0 +export VERSION=1.2.0 # if ca version not passed in, default to latest released version export CA_VERSION=$VERSION # current version of thirdparty images (couchdb, kafka and zookeeper) released -export THIRDPARTY_IMAGE_VERSION=0.4.7 +export THIRDPARTY_IMAGE_VERSION=0.4.8 export ARCH=$(echo "$(uname -s|tr '[:upper:]' '[:lower:]'|sed 's/mingw64_nt.*/windows/')-$(uname -m | sed 's/x86_64/amd64/g')") export MARCH=$(uname -m) From 6edd320ded01b62be6c43a7ad33a1367c8041861 Mon Sep 17 00:00:00 2001 From: Christopher Ferris Date: Thu, 5 Jul 2018 08:01:17 -0400 Subject: [PATCH 02/35] FAB-9297 fix README links and update bootstrap.sh Change-Id: I00cac1a0c01a777af887104064e7dfa775359359 Signed-off-by: Christopher Ferris --- README.md | 4 ++-- scripts/bootstrap.sh | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index f35817e8..fbefa729 100644 --- a/README.md +++ b/README.md @@ -9,11 +9,11 @@ intend to use to ensure alignment. ## Download Binaries and Docker Images -The [`scripts/bootstrap.sh`](https://github.com/hyperledger/fabric-samples/blob/release-1.1/scripts/bootstrap.sh) +The [`scripts/bootstrap.sh`](https://github.com/hyperledger/fabric-samples/blob/release-1.2/scripts/bootstrap.sh) script will preload all of the requisite docker images for Hyperledger Fabric and tag them with the 'latest' tag. Optionally, specify a version for fabric, fabric-ca and thirdparty images. Default versions -are 1.1.0, 1.1.0 and 0.4.7 respectively. +are 1.2.0, 1.2.0 and 0.4.10 respectively. ```bash ./scripts/bootstrap.sh [version] [ca version] [thirdparty_version] diff --git a/scripts/bootstrap.sh b/scripts/bootstrap.sh index b02d9004..96c6da31 100755 --- a/scripts/bootstrap.sh +++ b/scripts/bootstrap.sh @@ -10,7 +10,7 @@ export VERSION=1.2.0 # if ca version not passed in, default to latest released version export CA_VERSION=$VERSION # current version of thirdparty images (couchdb, kafka and zookeeper) released -export THIRDPARTY_IMAGE_VERSION=0.4.8 +export THIRDPARTY_IMAGE_VERSION=0.4.10 export ARCH=$(echo "$(uname -s|tr '[:upper:]' '[:lower:]'|sed 's/mingw64_nt.*/windows/')-$(uname -m | sed 's/x86_64/amd64/g')") export MARCH=$(uname -m) @@ -32,8 +32,8 @@ printHelp() { echo "-d - bypass docker image download" echo "-b - bypass download of platform-specific binaries" echo - echo "e.g. bootstrap.sh 1.1.1" - echo "would download docker images and binaries for version 1.1.1" + echo "e.g. bootstrap.sh 1.2.0 1.2.0 0.4.10" + echo "would download docker images and binaries for version 1.2.0 (fabric) 1.2.0 (fabric-ca) 0.4.10 (thirdparty)" } dockerFabricPull() { From c4bdc68e1b8a74792a3af9f35f647a87010e9203 Mon Sep 17 00:00:00 2001 From: susmita Date: Fri, 23 Feb 2018 12:06:53 -0500 Subject: [PATCH 03/35] [FAB-8479] Added Endorsement policy for balance transfer app in node-sdk samples. Added Endorsement policy in instantiate-chaincode. Change-Id: Ie7344353a8febf0f1e76f6a4edcb3035ab2d00e2 Signed-off-by: susmita --- balance-transfer/README.md | 32 +++++++++++++++++-- balance-transfer/app/instantiate-chaincode.js | 14 +++++++- balance-transfer/testAPIs.sh | 6 ++-- 3 files changed, 46 insertions(+), 6 deletions(-) diff --git a/balance-transfer/README.md b/balance-transfer/README.md index 553c67d3..7d551d25 100644 --- a/balance-transfer/README.md +++ b/balance-transfer/README.md @@ -173,13 +173,40 @@ curl -s -X POST \ ### Instantiate chaincode +This is the endorsement policy defined during instantiation. +This policy can be fulfilled when members from both orgs sign the transaction proposal. + +``` +{ + identities: [{ + role: { + name: 'member', + mspId: 'Org1MSP' + } + }, + { + role: { + name: 'member', + mspId: 'Org2MSP' + } + } + ], + policy: { + '2-of': [{ + 'signed-by': 0 + }, { + 'signed-by': 1 + }] + } +} +``` + ``` curl -s -X POST \ http://localhost:4000/channels/mychannel/chaincodes \ -H "authorization: Bearer " \ -H "content-type: application/json" \ -d '{ - "peers": ["peer0.org1.example.com","peer1.org1.example.com"], "chaincodeName":"mycc", "chaincodeVersion":"v0", "chaincodeType": "golang", @@ -190,13 +217,14 @@ curl -s -X POST \ ### Invoke request +This invoke request is signed by peers from both orgs, *org1* & *org2*. ``` curl -s -X POST \ http://localhost:4000/channels/mychannel/chaincodes/mycc \ -H "authorization: Bearer " \ -H "content-type: application/json" \ -d '{ - "peers": ["peer0.org1.example.com","peer1.org1.example.com"], + "peers": ["peer0.org1.example.com","peer0.org2.example.com"], "fcn":"move", "args":["a","b","10"] }' diff --git a/balance-transfer/app/instantiate-chaincode.js b/balance-transfer/app/instantiate-chaincode.js index 923be6b8..1c6455a5 100644 --- a/balance-transfer/app/instantiate-chaincode.js +++ b/balance-transfer/app/instantiate-chaincode.js @@ -50,7 +50,19 @@ var instantiateChaincode = async function(peers, channelName, chaincodeName, cha chaincodeType: chaincodeType, chaincodeVersion: chaincodeVersion, args: args, - txId: tx_id + txId: tx_id, + + // Use this to demonstrate the following policy: + // The policy can be fulfilled when members from both orgs signed. + 'endorsement-policy': { + identities: [ + { role: { name: 'member', mspId: 'Org1MSP' }}, + { role: { name: 'member', mspId: 'Org2MSP' }} + ], + policy: { + '2-of':[{ 'signed-by': 0 }, { 'signed-by': 1 }] + } + } }; if (functionName) diff --git a/balance-transfer/testAPIs.sh b/balance-transfer/testAPIs.sh index e83a672e..8528924c 100755 --- a/balance-transfer/testAPIs.sh +++ b/balance-transfer/testAPIs.sh @@ -144,7 +144,7 @@ curl -s -X POST \ echo echo -echo "POST instantiate chaincode on peer1 of Org1" +echo "POST instantiate chaincode on Org1" echo curl -s -X POST \ http://localhost:4000/channels/mychannel/chaincodes \ @@ -159,14 +159,14 @@ curl -s -X POST \ echo echo -echo "POST invoke chaincode on peers of Org1" +echo "POST invoke chaincode on peers of Org1 and Org2" echo TRX_ID=$(curl -s -X POST \ http://localhost:4000/channels/mychannel/chaincodes/mycc \ -H "authorization: Bearer $ORG1_TOKEN" \ -H "content-type: application/json" \ -d '{ - "peers": ["peer0.org1.example.com","peer1.org1.example.com"], + "peers": ["peer0.org1.example.com","peer0.org2.example.com"], "fcn":"move", "args":["a","b","10"] }') From a4a15cb3798a3a055d7e108354b3d5937e892a2e Mon Sep 17 00:00:00 2001 From: Bret Harrison Date: Thu, 19 Jul 2018 12:50:28 -0400 Subject: [PATCH 04/35] FAB-11220 Samples - remove EventHub Removed the use of the old EventHub from both FabCar and BalanceTransfer. Change-Id: Ia4a0bb443f95c462efde9b054058986ae8bd80fd Signed-off-by: Bret Harrison --- balance-transfer/app/join-channel.js | 60 +------------------ .../artifacts/network-config-aws.yaml | 5 -- .../artifacts/network-config.yaml | 5 -- fabcar/invoke.js | 15 ++--- 4 files changed, 11 insertions(+), 74 deletions(-) diff --git a/balance-transfer/app/join-channel.js b/balance-transfer/app/join-channel.js index 854994a6..4f1e34ed 100644 --- a/balance-transfer/app/join-channel.js +++ b/balance-transfer/app/join-channel.js @@ -47,50 +47,10 @@ var joinChannel = async function(channel_name, peers, username, org_name) { }; let genesis_block = await channel.getGenesisBlock(request); - // tell each peer to join and wait for the event hub of each peer to tell us - // that the channel has been created on each peer + // tell each peer to join and wait 10 seconds + // for the channel to be created on each peer var promises = []; - var block_registration_numbers = []; - let event_hubs = client.getEventHubsForOrg(org_name); - event_hubs.forEach((eh) => { - let configBlockPromise = new Promise((resolve, reject) => { - let event_timeout = setTimeout(() => { - let message = 'REQUEST_TIMEOUT:' + eh._ep._endpoint.addr; - logger.error(message); - eh.disconnect(); - reject(new Error(message)); - }, 60000); - let block_registration_number = eh.registerBlockEvent((block) => { - clearTimeout(event_timeout); - // a peer may have more than one channel so - // we must check that this block came from the channel we - // asked the peer to join - if (block.data.data.length === 1) { - // Config block must only contain one transaction - var channel_header = block.data.data[0].payload.header.channel_header; - if (channel_header.channel_id === channel_name) { - let message = util.format('EventHub % has reported a block update for channel %s',eh._ep._endpoint.addr,channel_name); - logger.info(message) - resolve(message); - } else { - let message = util.format('Unknown channel block event received from %s',eh._ep._endpoint.addr); - logger.error(message); - reject(new Error(message)); - } - } - }, (err) => { - clearTimeout(event_timeout); - let message = 'Problem setting up the event hub :'+ err.toString(); - logger.error(message); - reject(new Error(message)); - }); - // save the registration handle so able to deregister - block_registration_numbers.push(block_registration_number); - all_eventhubs.push(eh); //save for later so that we can shut it down - }); - promises.push(configBlockPromise); - eh.connect(); //this opens the event stream that must be shutdown at some point with a disconnect() - }); + promises.push(new Promise(resolve => setTimeout(resolve, 10000))); let join_request = { targets: peers, //using the peer names which only is allowed when a connection profile is loaded @@ -116,20 +76,6 @@ var joinChannel = async function(channel_name, peers, username, org_name) { logger.error(message); } } - // now see what each of the event hubs reported - for(let i in results) { - let event_hub_result = results[i]; - let event_hub = event_hubs[i]; - let block_registration_number = block_registration_numbers[i]; - logger.debug('Event results for event hub :%s',event_hub._ep._endpoint.addr); - if(typeof event_hub_result === 'string') { - logger.debug(event_hub_result); - } else { - if(!error_message) error_message = event_hub_result.toString(); - logger.debug(event_hub_result.toString()); - } - event_hub.unregisterBlockEvent(block_registration_number); - } } catch(error) { logger.error('Failed to join channel due to error: ' + error.stack ? error.stack : error); error_message = error.toString(); diff --git a/balance-transfer/artifacts/network-config-aws.yaml b/balance-transfer/artifacts/network-config-aws.yaml index d9ecd513..87912d71 100644 --- a/balance-transfer/artifacts/network-config-aws.yaml +++ b/balance-transfer/artifacts/network-config-aws.yaml @@ -167,9 +167,6 @@ peers: # this URL is used to send endorsement and query requests url: grpcs://ec2-13-59-99-140.us-east-2.compute.amazonaws.com:7051 - # this URL is used to connect the EventHub and registering event listeners - eventUrl: grpcs://ec2-13-59-99-140.us-east-2.compute.amazonaws.com:7053 - grpcOptions: ssl-target-name-override: peer0.org1.example.com tlsCACerts: @@ -185,7 +182,6 @@ peers: peer0.org2.example.com: url: grpcs://ec2-13-59-99-140.us-east-2.compute.amazonaws.com:8051 - eventUrl: grpcs://ec2-13-59-99-140.us-east-2.compute.amazonaws.com:8053 grpcOptions: ssl-target-name-override: peer0.org2.example.com tlsCACerts: @@ -193,7 +189,6 @@ peers: peer1.org2.example.com: url: grpcs://ec2-13-59-99-140.us-east-2.compute.amazonaws.com:8056 - eventUrl: grpcs://ec2-13-59-99-140.us-east-2.compute.amazonaws.com:8058 grpcOptions: ssl-target-name-override: peer1.org2.example.com tlsCACerts: diff --git a/balance-transfer/artifacts/network-config.yaml b/balance-transfer/artifacts/network-config.yaml index f7544dd9..1d6d9efe 100644 --- a/balance-transfer/artifacts/network-config.yaml +++ b/balance-transfer/artifacts/network-config.yaml @@ -167,9 +167,6 @@ peers: # this URL is used to send endorsement and query requests url: grpcs://localhost:7051 - # this URL is used to connect the EventHub and registering event listeners - eventUrl: grpcs://localhost:7053 - grpcOptions: ssl-target-name-override: peer0.org1.example.com tlsCACerts: @@ -177,7 +174,6 @@ peers: peer1.org1.example.com: url: grpcs://localhost:7056 - eventUrl: grpcs://localhost:7058 grpcOptions: ssl-target-name-override: peer1.org1.example.com tlsCACerts: @@ -185,7 +181,6 @@ peers: peer0.org2.example.com: url: grpcs://localhost:8051 - eventUrl: grpcs://localhost:8053 grpcOptions: ssl-target-name-override: peer0.org2.example.com tlsCACerts: diff --git a/fabcar/invoke.js b/fabcar/invoke.js index 221e2c00..2232303a 100644 --- a/fabcar/invoke.js +++ b/fabcar/invoke.js @@ -102,24 +102,21 @@ Fabric_Client.newDefaultKeyValueStore({ path: store_path // get an eventhub once the fabric client has a user assigned. The user // is required bacause the event registration must be signed - let event_hub = fabric_client.newEventHub(); - event_hub.setPeerAddr('grpc://localhost:7053'); + let event_hub = channel.newChannelEventHub(peer); // using resolve the promise so that result status may be processed // under the then clause rather than having the catch clause process // the status let txPromise = new Promise((resolve, reject) => { let handle = setTimeout(() => { + event_hub.unregisterTxEvent(transaction_id_string); event_hub.disconnect(); resolve({event_status : 'TIMEOUT'}); //we could use reject(new Error('Trnasaction did not complete within 30 seconds')); }, 3000); - event_hub.connect(); event_hub.registerTxEvent(transaction_id_string, (tx, code) => { // this is the callback for transaction event status // first some clean up of event listener clearTimeout(handle); - event_hub.unregisterTxEvent(transaction_id_string); - event_hub.disconnect(); // now let the application know what happened var return_status = {event_status : code, tx_id : transaction_id_string}; @@ -127,13 +124,17 @@ Fabric_Client.newDefaultKeyValueStore({ path: store_path console.error('The transaction was invalid, code = ' + code); resolve(return_status); // we could use reject(new Error('Problem with the tranaction, event status ::'+code)); } else { - console.log('The transaction has been committed on peer ' + event_hub._ep._endpoint.addr); + console.log('The transaction has been committed on peer ' + event_hub.getPeerAddr()); resolve(return_status); } }, (err) => { //this is the callback if something goes wrong with the event registration or processing reject(new Error('There was a problem with the eventhub ::'+err)); - }); + }, + {disconnect: true} //disconnect when complete + ); + event_hub.connect(); + }); promises.push(txPromise); From 0ca9e6e173ac8404752e55d6fd49af4178a9ccce Mon Sep 17 00:00:00 2001 From: rameshthoomu Date: Thu, 28 Jun 2018 12:23:39 -0400 Subject: [PATCH 05/35] FABN-833 Update Jenkinsfile to capture build artifacts Change-Id: Ie5eb6bb82b99ba12f7a4d417450b55d175d811b3 Signed-off-by: rameshthoomu --- Jenkinsfile | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Jenkinsfile b/Jenkinsfile index 9ccbf1db..a5836e26 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -91,4 +91,7 @@ node ('hyp-x') { // trigger build on x86_64 node throw err } } + stage("Archive Build artifacts") { + archiveArtifacts artifacts: '**/*.log' + } } From ca6959cb5dc046c21289ea4681382c13e05cdc73 Mon Sep 17 00:00:00 2001 From: rameshthoomu Date: Wed, 25 Jul 2018 15:39:10 -0400 Subject: [PATCH 06/35] FAB-11311 Update fabric image version Update fabric image version to 1.3.0-stable to pull the latest fabric and fabric-ca docker images Change-Id: I598b98afa205ca68b37598d159bf0fb9f36fd370 Signed-off-by: rameshthoomu --- scripts/Jenkins_Scripts/CI_Script.sh | 2 +- scripts/Jenkins_Scripts/byfn_eyfn.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/Jenkins_Scripts/CI_Script.sh b/scripts/Jenkins_Scripts/CI_Script.sh index 2451d6dc..453084a4 100755 --- a/scripts/Jenkins_Scripts/CI_Script.sh +++ b/scripts/Jenkins_Scripts/CI_Script.sh @@ -8,7 +8,7 @@ # exit on first error export BASE_FOLDER=$WORKSPACE/gopath/src/github.com/hyperledger -export PROJECT_VERSION=1.2.0-stable +export PROJECT_VERSION=1.3.0-stable export NEXUS_URL=nexus3.hyperledger.org:10001 export ORG_NAME="hyperledger/fabric" export NODE_VER=8.9.4 # Default nodejs version diff --git a/scripts/Jenkins_Scripts/byfn_eyfn.sh b/scripts/Jenkins_Scripts/byfn_eyfn.sh index fea4fc1e..49cd6680 100755 --- a/scripts/Jenkins_Scripts/byfn_eyfn.sh +++ b/scripts/Jenkins_Scripts/byfn_eyfn.sh @@ -13,7 +13,7 @@ MVN_METADATA=$(echo "https://nexus.hyperledger.org/content/repositories/releases curl -L "$MVN_METADATA" > maven-metadata.xml RELEASE_TAG=$(cat maven-metadata.xml | grep release) COMMIT=$(echo $RELEASE_TAG | awk -F - '{ print $4 }' | cut -d "<" -f1) -VERSION=1.2.0 +VERSION=1.3.0 echo "-----------> BASE_VERSION = $VERSION" cd $BASE_FOLDER/fabric-samples || exit curl https://nexus.hyperledger.org/content/repositories/releases/org/hyperledger/fabric/hyperledger-fabric-stable/$MARCH-$ARCH.$VERSION-stable-$COMMIT/hyperledger-fabric-stable-$MARCH-$ARCH.$VERSION-stable-$COMMIT.tar.gz | tar xz From 5930dfc06a2f77f3c7573db606f432945932ec28 Mon Sep 17 00:00:00 2001 From: rameshthoomu Date: Mon, 6 Aug 2018 12:02:57 -0400 Subject: [PATCH 07/35] FAB-11488 Update CI script Update byfn_eyfn.sh script to fetch the binaries from the correct nexus url. Change-Id: I0ea675235cc0dce691b8a1bbf30951504f0a8112 Signed-off-by: rameshthoomu --- scripts/Jenkins_Scripts/byfn_eyfn.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/scripts/Jenkins_Scripts/byfn_eyfn.sh b/scripts/Jenkins_Scripts/byfn_eyfn.sh index 49cd6680..7785bdd2 100755 --- a/scripts/Jenkins_Scripts/byfn_eyfn.sh +++ b/scripts/Jenkins_Scripts/byfn_eyfn.sh @@ -9,14 +9,14 @@ ARCH=$(dpkg --print-architecture) echo "-----------> ARCH" $ARCH MARCH=$(uname -s|tr '[:upper:]' '[:lower:]') echo "-----------> MARCH" $MARCH -MVN_METADATA=$(echo "https://nexus.hyperledger.org/content/repositories/releases/org/hyperledger/fabric/hyperledger-fabric-stable/maven-metadata.xml") +VERSION=1.3.0 +MVN_METADATA=$(echo "https://nexus.hyperledger.org/content/repositories/releases/org/hyperledger/fabric/hyperledger-fabric-$VERSION-stable/maven-metadata.xml") curl -L "$MVN_METADATA" > maven-metadata.xml RELEASE_TAG=$(cat maven-metadata.xml | grep release) COMMIT=$(echo $RELEASE_TAG | awk -F - '{ print $4 }' | cut -d "<" -f1) -VERSION=1.3.0 echo "-----------> BASE_VERSION = $VERSION" cd $BASE_FOLDER/fabric-samples || exit -curl https://nexus.hyperledger.org/content/repositories/releases/org/hyperledger/fabric/hyperledger-fabric-stable/$MARCH-$ARCH.$VERSION-stable-$COMMIT/hyperledger-fabric-stable-$MARCH-$ARCH.$VERSION-stable-$COMMIT.tar.gz | tar xz +curl https://nexus.hyperledger.org/content/repositories/releases/org/hyperledger/fabric/hyperledger-fabric-$VERSION-stable/$MARCH-$ARCH.$VERSION-stable-$COMMIT/hyperledger-fabric-$VERSION-stable-$MARCH-$ARCH.$VERSION-stable-$COMMIT.tar.gz | tar xz cd first-network || exit export PATH=gopath/src/github.com/hyperledger/fabric-samples/bin:$PATH From bfdc0b6e7a7caab2174c4b05779cf3cbc9b73cb5 Mon Sep 17 00:00:00 2001 From: clydedacruz Date: Wed, 8 Aug 2018 23:32:53 +0530 Subject: [PATCH 08/35] FAB-11518 Fixed typo in instatiate-chaincode.js and removed unused imports from other JavaScript files in balance-transfer/app Change-Id: If9695c4f51e9c0835230b2c7f969cbf4aa132675 Signed-off-by: Clyde DCruz --- balance-transfer/app/create-channel.js | 1 - balance-transfer/app/helper.js | 10 ---------- balance-transfer/app/install-chaincode.js | 6 +----- balance-transfer/app/instantiate-chaincode.js | 7 ++----- balance-transfer/app/invoke-transaction.js | 3 --- balance-transfer/app/join-channel.js | 4 +--- balance-transfer/app/query.js | 3 --- 7 files changed, 4 insertions(+), 30 deletions(-) diff --git a/balance-transfer/app/create-channel.js b/balance-transfer/app/create-channel.js index 80e27c19..754d18a0 100644 --- a/balance-transfer/app/create-channel.js +++ b/balance-transfer/app/create-channel.js @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -var util = require('util'); var fs = require('fs'); var path = require('path'); diff --git a/balance-transfer/app/helper.js b/balance-transfer/app/helper.js index 42f579f6..64896191 100644 --- a/balance-transfer/app/helper.js +++ b/balance-transfer/app/helper.js @@ -20,19 +20,9 @@ logger.setLevel('DEBUG'); var path = require('path'); var util = require('util'); -var copService = require('fabric-ca-client'); var hfc = require('fabric-client'); hfc.setLogger(logger); -var ORGS = hfc.getConfigSetting('network-config'); - -var clients = {}; -var channels = {}; -var caClients = {}; - -var sleep = async function (sleep_time_ms) { - return new Promise(resolve => setTimeout(resolve, sleep_time_ms)); -} async function getClientForOrg (userorg, username) { logger.debug('getClientForOrg - ****** START %s %s', userorg, username) diff --git a/balance-transfer/app/install-chaincode.js b/balance-transfer/app/install-chaincode.js index 5d976f4e..938e59f8 100644 --- a/balance-transfer/app/install-chaincode.js +++ b/balance-transfer/app/install-chaincode.js @@ -14,13 +14,9 @@ * limitations under the License. */ 'use strict'; -var path = require('path'); -var fs = require('fs'); var util = require('util'); -var config = require('../config.json'); var helper = require('./helper.js'); var logger = helper.getLogger('install-chaincode'); -var tx_id = null; var installChaincode = async function(peers, chaincodeName, chaincodePath, chaincodeVersion, chaincodeType, username, org_name) { @@ -76,7 +72,7 @@ var installChaincode = async function(peers, chaincodeName, chaincodePath, } if (!error_message) { - let message = util.format('Successfully install chaincode'); + let message = util.format('Successfully installed chaincode'); logger.info(message); // build a response to send back to the REST caller let response = { diff --git a/balance-transfer/app/instantiate-chaincode.js b/balance-transfer/app/instantiate-chaincode.js index 1c6455a5..aa8e0404 100644 --- a/balance-transfer/app/instantiate-chaincode.js +++ b/balance-transfer/app/instantiate-chaincode.js @@ -14,10 +14,7 @@ * limitations under the License. */ 'use strict'; -var path = require('path'); -var fs = require('fs'); var util = require('util'); -var hfc = require('fabric-client'); var helper = require('./helper.js'); var logger = helper.getLogger('instantiate-chaincode'); @@ -117,7 +114,7 @@ var instantiateChaincode = async function(peers, channelName, chaincodeName, cha clearTimeout(event_timeout); if (code !== 'VALID') { - let message = until.format('The chaincode instantiate transaction was invalid, code:%s',code); + let message = util.format('The chaincode instantiate transaction was invalid, code:%s',code); logger.error(message); reject(new Error(message)); } else { @@ -187,7 +184,7 @@ var instantiateChaincode = async function(peers, channelName, chaincodeName, cha if (!error_message) { let message = util.format( - 'Successfully instantiate chaingcode in organization %s to the channel \'%s\'', + 'Successfully instantiate chaincode in organization %s to the channel \'%s\'', org_name, channelName); logger.info(message); // build a response to send back to the REST caller diff --git a/balance-transfer/app/invoke-transaction.js b/balance-transfer/app/invoke-transaction.js index 9232f707..a2176209 100644 --- a/balance-transfer/app/invoke-transaction.js +++ b/balance-transfer/app/invoke-transaction.js @@ -14,10 +14,7 @@ * limitations under the License. */ 'use strict'; -var path = require('path'); -var fs = require('fs'); var util = require('util'); -var hfc = require('fabric-client'); var helper = require('./helper.js'); var logger = helper.getLogger('invoke-chaincode'); diff --git a/balance-transfer/app/join-channel.js b/balance-transfer/app/join-channel.js index 4f1e34ed..b5eedfe9 100644 --- a/balance-transfer/app/join-channel.js +++ b/balance-transfer/app/join-channel.js @@ -14,8 +14,6 @@ * limitations under the License. */ var util = require('util'); -var path = require('path'); -var fs = require('fs'); var helper = require('./helper.js'); var logger = helper.getLogger('Join-Channel'); @@ -71,7 +69,7 @@ var joinChannel = async function(channel_name, peers, username, org_name) { if(peer_result.response && peer_result.response.status == 200) { logger.info('Successfully joined peer to the channel %s',channel_name); } else { - let message = util.format('Failed to joined peer to the channel %s',channel_name); + let message = util.format('Failed to join peer to the channel %s',channel_name); error_message = message; logger.error(message); } diff --git a/balance-transfer/app/query.js b/balance-transfer/app/query.js index 8607dde8..3ff95022 100644 --- a/balance-transfer/app/query.js +++ b/balance-transfer/app/query.js @@ -13,10 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -var path = require('path'); -var fs = require('fs'); var util = require('util'); -var hfc = require('fabric-client'); var helper = require('./helper.js'); var logger = helper.getLogger('Query'); From cbbbc78b44da4b1e599deb5f63adfb71388be616 Mon Sep 17 00:00:00 2001 From: Yuki Kondo Date: Mon, 13 Aug 2018 18:58:19 +0000 Subject: [PATCH 09/35] [FAB-11577] Fix balance transfer to install Chaincode Balance transfer fails to install Chaincode since there is a undeclared variable "tx_id". However, "tx_id" is not required in ChaincodeInstallRequest. This CR removes the line getting transactionId to execute installChaincode correctly. Change-Id: Ia62844172ceecd84fa9a9f2e40e804d1f7a7499b Signed-off-by: Yuki Kondo --- balance-transfer/app/install-chaincode.js | 1 - 1 file changed, 1 deletion(-) diff --git a/balance-transfer/app/install-chaincode.js b/balance-transfer/app/install-chaincode.js index 938e59f8..2bc8bbb7 100644 --- a/balance-transfer/app/install-chaincode.js +++ b/balance-transfer/app/install-chaincode.js @@ -30,7 +30,6 @@ var installChaincode = async function(peers, chaincodeName, chaincodePath, var client = await helper.getClientForOrg(org_name, username); logger.debug('Successfully got the fabric client for the organization "%s"', org_name); - tx_id = client.newTransactionID(true); //get an admin transactionID var request = { targets: peers, chaincodePath: chaincodePath, From d77665186ed60dec51039ec8ba388f9ea1dc9c0c Mon Sep 17 00:00:00 2001 From: Anthony O'Dowd Date: Fri, 24 Aug 2018 15:50:23 +0100 Subject: [PATCH 10/35] FAB-11723 Developing Apps: Sample pt 1 -- contract Change-Id: Ia61aae9b83c3297dfe28fd475c585e021186a4aa Signed-off-by: Anthony O'Dowd --- commercial-paper/contract/.editorconfig | 16 +++ commercial-paper/contract/.eslintignore | 5 + commercial-paper/contract/.eslintrc.js | 37 +++++ commercial-paper/contract/.npmignore | 77 ++++++++++ commercial-paper/contract/index.js | 7 + commercial-paper/contract/lib/cpcontract.js | 113 +++++++++++++++ commercial-paper/contract/lib/cpstate.js | 148 ++++++++++++++++++++ commercial-paper/contract/lib/utils.js | 34 +++++ commercial-paper/contract/package.json | 45 ++++++ commercial-paper/contract/test/contract.js | 41 ++++++ 10 files changed, 523 insertions(+) create mode 100755 commercial-paper/contract/.editorconfig create mode 100644 commercial-paper/contract/.eslintignore create mode 100644 commercial-paper/contract/.eslintrc.js create mode 100644 commercial-paper/contract/.npmignore create mode 100644 commercial-paper/contract/index.js create mode 100644 commercial-paper/contract/lib/cpcontract.js create mode 100644 commercial-paper/contract/lib/cpstate.js create mode 100644 commercial-paper/contract/lib/utils.js create mode 100644 commercial-paper/contract/package.json create mode 100644 commercial-paper/contract/test/contract.js diff --git a/commercial-paper/contract/.editorconfig b/commercial-paper/contract/.editorconfig new file mode 100755 index 00000000..75a13be2 --- /dev/null +++ b/commercial-paper/contract/.editorconfig @@ -0,0 +1,16 @@ +# +# SPDX-License-Identifier: Apache-2.0 +# + +root = true + +[*] +indent_style = space +indent_size = 4 +end_of_line = lf +charset = utf-8 +trim_trailing_whitespace = true +insert_final_newline = true + +[*.md] +trim_trailing_whitespace = false diff --git a/commercial-paper/contract/.eslintignore b/commercial-paper/contract/.eslintignore new file mode 100644 index 00000000..15958470 --- /dev/null +++ b/commercial-paper/contract/.eslintignore @@ -0,0 +1,5 @@ +# +# SPDX-License-Identifier: Apache-2.0 +# + +coverage diff --git a/commercial-paper/contract/.eslintrc.js b/commercial-paper/contract/.eslintrc.js new file mode 100644 index 00000000..6772c660 --- /dev/null +++ b/commercial-paper/contract/.eslintrc.js @@ -0,0 +1,37 @@ +/* +SPDX-License-Identifier: Apache-2.0 +*/ + +module.exports = { + env: { + node: true, + mocha: true + }, + parserOptions: { + ecmaVersion: 8, + sourceType: 'script' + }, + extends: "eslint:recommended", + rules: { + indent: ['error', 4], + 'linebreak-style': ['error', 'unix'], + quotes: ['error', 'single'], + semi: ['error', 'always'], + 'no-unused-vars': ['error', { args: 'none' }], + 'no-console': 'off', + curly: 'error', + eqeqeq: 'error', + 'no-throw-literal': 'error', + strict: 'error', + 'no-var': 'error', + 'dot-notation': 'error', + 'no-tabs': 'error', + 'no-trailing-spaces': 'error', + 'no-use-before-define': 'error', + 'no-useless-call': 'error', + 'no-with': 'error', + 'operator-linebreak': 'error', + yoda: 'error', + 'quote-props': ['error', 'as-needed'] + } +}; diff --git a/commercial-paper/contract/.npmignore b/commercial-paper/contract/.npmignore new file mode 100644 index 00000000..a00ca941 --- /dev/null +++ b/commercial-paper/contract/.npmignore @@ -0,0 +1,77 @@ +# +# SPDX-License-Identifier: Apache-2.0 +# + +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* + +# Runtime data +pids +*.pid +*.seed +*.pid.lock + +# Directory for instrumented libs generated by jscoverage/JSCover +lib-cov + +# Coverage directory used by tools like istanbul +coverage + +# nyc test coverage +.nyc_output + +# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) +.grunt + +# Bower dependency directory (https://bower.io/) +bower_components + +# node-waf configuration +.lock-wscript + +# Compiled binary addons (https://nodejs.org/api/addons.html) +build/Release + +# Dependency directories +node_modules/ +jspm_packages/ + +# TypeScript v1 declaration files +typings/ + +# Optional npm cache directory +.npm + +# Optional eslint cache +.eslintcache + +# Optional REPL history +.node_repl_history + +# Output of 'npm pack' +*.tgz + +# Yarn Integrity file +.yarn-integrity + +# dotenv environment variables file +.env + +# parcel-bundler cache (https://parceljs.org/) +.cache + +# next.js build output +.next + +# nuxt.js build output +.nuxt + +# vuepress build output +.vuepress/dist + +# Serverless directories +.serverless diff --git a/commercial-paper/contract/index.js b/commercial-paper/contract/index.js new file mode 100644 index 00000000..ddc4f2c6 --- /dev/null +++ b/commercial-paper/contract/index.js @@ -0,0 +1,7 @@ +/* +SPDX-License-Identifier: Apache-2.0 +*/ + +'use strict'; + +module.exports.contracts = require('./lib/cpcontract.js'); diff --git a/commercial-paper/contract/lib/cpcontract.js b/commercial-paper/contract/lib/cpcontract.js new file mode 100644 index 00000000..ed793fd1 --- /dev/null +++ b/commercial-paper/contract/lib/cpcontract.js @@ -0,0 +1,113 @@ +/* +SPDX-License-Identifier: Apache-2.0 +*/ + +'use strict'; + +// Smart contract API brought into scope +const {Contract} = require('fabric-contract-api'); + +// Commercial paper classes brought into scope +const {CommercialPaper, CommercialPaperList} = require('./cpstate.js'); + +/** + * Define the commercial paper smart contract extending Fabric Contract class + */ +class CommercialPaperContract extends Contract { + + /** + * Each smart contract can have a unique namespace; useful when multiple + * smart contracts per file. + * Use transaction context (ctx) to access list of all commercial papers. + */ + constructor() { + super('org.papernet.commercialpaper'); + + this.setBeforeFn = (ctx)=>{ + ctx.cpList = new CommercialPaperList(ctx, 'COMMERCIALPAPER'); + return ctx; + }; + } + + /** + * Issue commercial paper + * @param {TxContext} ctx the transaction context + * @param {String} issuer commercial paper issuer + * @param {Integer} paperNumber paper number for this issuer + * @param {String} issueDateTime paper issue date + * @param {String} maturityDateTime paper maturity date + * @param {Integer} faceValue face value of paper + */ + async issue(ctx, issuer, paperNumber, issueDateTime, maturityDateTime, faceValue) { + + let cp = new CommercialPaper(issuer, paperNumber, issueDateTime, maturityDateTime, faceValue); + + // {issuer:"MagnetoCorp", paperNumber:"00001", "May31 2020", "Nov 30 2020", "5M USD"} + + await ctx.cpList.addPaper(cp); + } + + /** + * Buy commercial paper + * @param {TxContext} ctx the transaction context + * @param {String} issuer commercial paper issuer + * @param {Integer} paperNumber paper number for this issuer + * @param {String} currentOwner current owner of paper + * @param {String} newOwner new owner of paper + * @param {Integer} price price paid for this paper + * @param {String} purchaseDateTime time paper was purchased (i.e. traded) + */ + async buy(ctx, issuer, paperNumber, currentOwner, newOwner, price, purchaseDateTime) { + + let cpKey = CommercialPaper.createKey(issuer, paperNumber); + let cp = await ctx.cpList.getPaper(cpKey); + + if (cp.getOwner() !== currentOwner) { + throw new Error('Paper '+issuer+paperNumber+' is not owned by '+currentOwner); + } + // First buy moves state from ISSUED to TRADING + if (cp.isIssued()) { + cp.setTrading(); + } + // Check paper is TRADING, not REDEEMED + if (cp.IsTrading()) { + cp.setOwner(newOwner); + } else { + throw new Error('Paper '+issuer+paperNumber+' is not trading. Current state = '+cp.getCurrentState()); + } + + await ctx.cpList.updatePaper(cp); + } + + /** + * Redeem commercial paper + * @param {TxContext} ctx the transaction context + * @param {String} issuer commercial paper issuer + * @param {Integer} paperNumber paper number for this issuer + * @param {String} redeemingOwner redeeming owner of paper + * @param {String} redeemDateTime time paper was redeemed + */ + async redeem(ctx, issuer, paperNumber, redeemingOwner, redeemDateTime) { + + let cpKey = CommercialPaper.createKey(issuer, paperNumber); + let cp = await ctx.cpList.getPaper(cpKey); + + // Check paper is TRADING, not REDEEMED + if (cp.IsRedeemed()) { + throw new Error('Paper '+issuer+paperNumber+' already redeemed'); + } + + // Verify that the redeemer owns the commercial paper before redeeming it + if (cp.getOwner() === redeemingOwner) { + cp.setOwner(cp.getIssuer()); + cp.setRedeemed(); + } else { + throw new Error('Redeeming owner does not own paper'+issuer+paperNumber); + } + + await ctx.cpList.updatePaper(cp); + } + +} + +module.exports = CommericalPaperContract; diff --git a/commercial-paper/contract/lib/cpstate.js b/commercial-paper/contract/lib/cpstate.js new file mode 100644 index 00000000..ad5222cd --- /dev/null +++ b/commercial-paper/contract/lib/cpstate.js @@ -0,0 +1,148 @@ +/* +SPDX-License-Identifier: Apache-2.0 +*/ + +'use strict'; + +// Helpful utilities class +const Utils = require('./utils.js'); + +// Enumeration of commercial paper state values +const cpState = { + ISSUED: 1, + TRADING: 2, + REDEEMED: 3 +}; + +/** + * CommercialPaper class defines a commercial paper state + */ +class CommercialPaper { + + /** + * Construct a commercial paper. Initial state is issued. + */ + constructor(issuer, paperNumber, issueDateTime, maturityDateTime, faceValue) { + this.issuer = issuer; + this.paperNumber = paperNumber; + this.owner = issuer; + this.issueDateTime = issueDateTime; + this.maturityDateTime = maturityDateTime; + this.faceValue = faceValue; + this.currentState = cpState.ISSUED; + this.key = CommercialPaper.createKey(issuer, paperNumber); + } + + /** + * The commercial paper is uniquely identified by its key. + * The key is a simple composite of issuer and paper number as strings. + */ + static createKey(issuer, paperNumber) { + return JSON.stringify(issuer) + JSON.stringify(paperNumber); + } + + /** + * Basic getters and setters + */ + getKey() { + return this.key; + } + + getIssuer() { + return this.issuer; + } + + setIssuer(newIssuer) { + this.issuer = newIssuer; + } + + getOwner() { + return this.owner; + } + + setOwner(newOwner) { + this.owner = newOwner; + } + + /** + * Useful methods to encapsulate commercial paper states + */ + setTrading() { + this.currentState = cpState.TRADING; + } + + setRedeemed() { + this.currentState = cpState.REDEEMED; + } + + isTrading() { + return this.currentState === cpState.TRADING; + } + + isRedeemed() { + return this.currentState === cpState.REDEEMED; + } + +} + +/** + * CommercialPaperList provides a virtual container to access all + * commercial papers. Each paper has unique key which associates it + * with the container, rather than the container containing a link to + * the paper. This is important in Fabric becuase it minimizes + * collisions for parallel transactions on different papers. + */ +class CommercialPaperList { + + /** + * For this sample, it is sufficient to create a commercial paper list + * using a fixed container prefix. The transaction context is saved to + * access Fabric APIs when required. + */ + constructor(ctx, prefix) { + this.api = ctx.stub; + this.prefix = prefix; + } + + /** + * Add a paper to the list. Creates a new state in worldstate with + * appropriate composite key. Note that paper defines its own key. + * Paper object is serialized before writing. + */ + async addPaper(cp) { + let key = this.api.createCompositeKey(this.prefix, [cp.getKey()]); + let data = Utils.serialize(cp); + await this.api.putState(key, data); + } + + /** + * Get a paper from the list using issuer and paper number. Forms composite + * keys to retrieve data from world state. State data is deserialized + * into paper object before being returned. + */ + async getPaper(key) { + let key = this.api.createCompositeKey(this.prefix, [key]); + let data = await this.api.getState(key); + let cp = Utils.deserialize(data); + return cp; + } + + /** + * Update a paper in the list. Puts the new state in world state with + * appropriate composite key. Note that paper defines its own key. + * Paper object is serialized before writing. Logic is very similar to + * addPaper() but kept separate becuase it is semantically distinct, and + * may change. + */ + async updatePaper(cp) { + let key = this.api.createCompositeKey(this.prefix, [cp.getKey()]); + let data = Utils.serialize(cp); + await this.api.putState(key, data); + } + +} + +module.exports = { + CommercialPaper, + CommercialPaperList +}; diff --git a/commercial-paper/contract/lib/utils.js b/commercial-paper/contract/lib/utils.js new file mode 100644 index 00000000..2a2c08ad --- /dev/null +++ b/commercial-paper/contract/lib/utils.js @@ -0,0 +1,34 @@ +/* +SPDX-License-Identifier: Apache-2.0 +*/ + +'use strict'; + +/** + * Utility class for data, object mapulation, e.g. serialization + */ + +class Utils { + + /** + * Convert object to buffer containing JSON data serialization + * Typically used before putState() ledger API + * @param {Object} object object to serialize + * @return {buffer} buffer with the data to store + */ + static serialize(object){ + return Buffer.from(JSON.stringify(object)); + } + + /** + * Deserialize object, i.e. Covert serialized data to JSON object + * Typically used after getState() ledger API + * @param {Object} data object to deserialize + * @return {json} json with the data to store + */ + static deserialize(data){ + return JSON.parse(data); + } +} + +module.exports = Utils; diff --git a/commercial-paper/contract/package.json b/commercial-paper/contract/package.json new file mode 100644 index 00000000..5741509f --- /dev/null +++ b/commercial-paper/contract/package.json @@ -0,0 +1,45 @@ +{ + "name": "smart-contract", + "version": "0.0.1", + "description": "Smart Contract", + "engines": { + "node": ">=8", + "npm": ">=5" + }, + "scripts": { + "lint": "eslint .", + "pretest": "npm run lint", + "test": "nyc mocha --recursive", + "start": "startChaincode" + }, + "engineStrict": true, + "author": "Anthony ODowd", + "license": "Apache-2.0", + "dependencies": { + "fabric-shim": "unstable", + "fabric-contract-api": "unstable" + }, + "devDependencies": { + "chai": "^4.1.2", + "eslint": "^4.19.1", + "mocha": "^5.2.0", + "nyc": "^12.0.2", + "sinon": "^6.0.0" + }, + "nyc": { + "exclude": [ + "coverage/**", + "test/**" + ], + "reporter": [ + "text-summary", + "html" + ], + "all": true, + "check-coverage": true, + "statements": 100, + "branches": 100, + "functions": 100, + "lines": 100 + } +} diff --git a/commercial-paper/contract/test/contract.js b/commercial-paper/contract/test/contract.js new file mode 100644 index 00000000..e0aafd5e --- /dev/null +++ b/commercial-paper/contract/test/contract.js @@ -0,0 +1,41 @@ +/* +SPDX-License-Identifier: Apache-2.0 +*/ +'use strict'; + +const Chaincode = require('../lib/chaincode'); +const { Stub } = require('fabric-shim'); + +require('chai').should(); +const sinon = require('sinon'); + +describe('Chaincode', () => { + + describe('#Init', () => { + + it('should work', async () => { + const cc = new Chaincode(); + const stub = sinon.createStubInstance(Stub); + stub.getFunctionAndParameters.returns({ fcn: 'initFunc', params: [] }); + const res = await cc.Init(stub); + res.status.should.equal(Stub.RESPONSE_CODE.OK); + }); + + }); + + describe('#Invoke', async () => { + + it('should work', async () => { + const cc = new Chaincode(); + const stub = sinon.createStubInstance(Stub); + stub.getFunctionAndParameters.returns({ fcn: 'initFunc', params: [] }); + let res = await cc.Init(stub); + res.status.should.equal(Stub.RESPONSE_CODE.OK); + stub.getFunctionAndParameters.returns({ fcn: 'invokeFunc', params: [] }); + res = await cc.Invoke(stub); + res.status.should.equal(Stub.RESPONSE_CODE.OK); + }); + + }); + +}); From 4030ebdb3d3a8b97d3e7ecef95fcf2b51121b235 Mon Sep 17 00:00:00 2001 From: gennady Date: Tue, 31 Jul 2018 00:05:49 +0300 Subject: [PATCH 11/35] [FAB-11397] Adding java cc Added java project sources under chaincode Added support for "-l java" to byfn.sh Change-Id: I7038aed9b21ad9bf51bcb58c6b71ceb1f161813f Signed-off-by: gennady --- .../chaincode_example02/java/build.gradle | 34 +++++ .../chaincode_example02/java/settings.gradle | 7 + .../fabric/example/SimpleChaincode.java | 142 ++++++++++++++++++ first-network/scripts/script.sh | 4 + 4 files changed, 187 insertions(+) create mode 100644 chaincode/chaincode_example02/java/build.gradle create mode 100644 chaincode/chaincode_example02/java/settings.gradle create mode 100644 chaincode/chaincode_example02/java/src/main/java/org/hyperledger/fabric/example/SimpleChaincode.java diff --git a/chaincode/chaincode_example02/java/build.gradle b/chaincode/chaincode_example02/java/build.gradle new file mode 100644 index 00000000..1f45bcdd --- /dev/null +++ b/chaincode/chaincode_example02/java/build.gradle @@ -0,0 +1,34 @@ +/* + * Copyright IBM Corp. 2018 All Rights Reserved. + * + * SPDX-License-Identifier: Apache-2.0 + */ +plugins { + id 'com.github.johnrengelman.shadow' version '2.0.3' + id 'java' +} + +group 'org.hyperledger.fabric' +version '1.0-SNAPSHOT' + +sourceCompatibility = 1.8 + +repositories { + mavenLocal() + mavenCentral() +} + +dependencies { + compile group: 'org.hyperledger.fabric', name: 'fabric-chaincode-shim', version: '1.3.0-SNAPSHOT' + testCompile group: 'junit', name: 'junit', version: '4.12' +} + +shadowJar { + baseName = 'chaincode' + version = null + classifier = null + + manifest { + attributes 'Main-Class': 'org.hyperledger.fabric.example.SimpleChaincode' + } +} diff --git a/chaincode/chaincode_example02/java/settings.gradle b/chaincode/chaincode_example02/java/settings.gradle new file mode 100644 index 00000000..9ce14a66 --- /dev/null +++ b/chaincode/chaincode_example02/java/settings.gradle @@ -0,0 +1,7 @@ +/* + * Copyright IBM Corp. 2017 All Rights Reserved. + * + * SPDX-License-Identifier: Apache-2.0 + */ +rootProject.name = 'fabric-chaincode-example-gradle' + diff --git a/chaincode/chaincode_example02/java/src/main/java/org/hyperledger/fabric/example/SimpleChaincode.java b/chaincode/chaincode_example02/java/src/main/java/org/hyperledger/fabric/example/SimpleChaincode.java new file mode 100644 index 00000000..dd93a4e0 --- /dev/null +++ b/chaincode/chaincode_example02/java/src/main/java/org/hyperledger/fabric/example/SimpleChaincode.java @@ -0,0 +1,142 @@ +/* +Copyright IBM Corp., DTCC All Rights Reserved. + +SPDX-License-Identifier: Apache-2.0 +*/ +package org.hyperledger.fabric.example; + +import java.util.List; + +import com.google.protobuf.ByteString; +import io.netty.handler.ssl.OpenSsl; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.hyperledger.fabric.shim.ChaincodeBase; +import org.hyperledger.fabric.shim.ChaincodeStub; + +import static java.nio.charset.StandardCharsets.UTF_8; + +public class SimpleChaincode extends ChaincodeBase { + + private static Log _logger = LogFactory.getLog(SimpleChaincode.class); + + @Override + public Response init(ChaincodeStub stub) { + try { + _logger.info("Init java simple chaincode"); + String func = stub.getFunction(); + if (!func.equals("init")) { + return newErrorResponse("function other than init is not supported"); + } + List args = stub.getParameters(); + if (args.size() != 4) { + newErrorResponse("Incorrect number of arguments. Expecting 4"); + } + // Initialize the chaincode + String account1Key = args.get(0); + int account1Value = Integer.parseInt(args.get(1)); + String account2Key = args.get(2); + int account2Value = Integer.parseInt(args.get(3)); + + _logger.info(String.format("account %s, value = %s; account %s, value %s", account1Key, account1Value, account2Key, account2Value)); + stub.putStringState(account1Key, args.get(1)); + stub.putStringState(account2Key, args.get(3)); + + return newSuccessResponse(); + } catch (Throwable e) { + return newErrorResponse(e); + } + } + + @Override + public Response invoke(ChaincodeStub stub) { + try { + _logger.info("Invoke java simple chaincode"); + String func = stub.getFunction(); + List params = stub.getParameters(); + if (func.equals("invoke")) { + return invoke(stub, params); + } + if (func.equals("delete")) { + return delete(stub, params); + } + if (func.equals("query")) { + return query(stub, params); + } + return newErrorResponse("Invalid invoke function name. Expecting one of: [\"invoke\", \"delete\", \"query\"]"); + } catch (Throwable e) { + return newErrorResponse(e); + } + } + + private Response invoke(ChaincodeStub stub, List args) { + if (args.size() != 3) { + return newErrorResponse("Incorrect number of arguments. Expecting 3"); + } + String accountFromKey = args.get(0); + String accountToKey = args.get(1); + + String accountFromValueStr = stub.getStringState(accountFromKey); + if (accountFromValueStr == null) { + return newErrorResponse(String.format("Entity %s not found", accountFromKey)); + } + int accountFromValue = Integer.parseInt(accountFromValueStr); + + String accountToValueStr = stub.getStringState(accountToKey); + if (accountToValueStr == null) { + return newErrorResponse(String.format("Entity %s not found", accountToKey)); + } + int accountToValue = Integer.parseInt(accountToValueStr); + + int amount = Integer.parseInt(args.get(2)); + + if (amount > accountFromValue) { + return newErrorResponse(String.format("not enough money in account %s", accountFromKey)); + } + + accountFromValue -= amount; + accountToValue += amount; + + _logger.info(String.format("new value of A: %s", accountFromValue)); + _logger.info(String.format("new value of B: %s", accountToValue)); + + stub.putStringState(accountFromKey, Integer.toString(accountFromValue)); + stub.putStringState(accountToKey, Integer.toString(accountToValue)); + + _logger.info("Transfer complete"); + + return newSuccessResponse("invoke finished successfully", ByteString.copyFrom(accountFromKey + ": " + accountFromValue + " " + accountToKey + ": " + accountToValue, UTF_8).toByteArray()); + } + + // Deletes an entity from state + private Response delete(ChaincodeStub stub, List args) { + if (args.size() != 1) { + return newErrorResponse("Incorrect number of arguments. Expecting 1"); + } + String key = args.get(0); + // Delete the key from the state in ledger + stub.delState(key); + return newSuccessResponse(); + } + + // query callback representing the query of a chaincode + private Response query(ChaincodeStub stub, List args) { + if (args.size() != 1) { + return newErrorResponse("Incorrect number of arguments. Expecting name of the person to query"); + } + String key = args.get(0); + //byte[] stateBytes + String val = stub.getStringState(key); + if (val == null) { + return newErrorResponse(String.format("Error: state for %s is null", key)); + } + _logger.info(String.format("Query Response:\nName: %s, Amount: %s\n", key, val)); + return newSuccessResponse(val, ByteString.copyFrom(val, UTF_8).toByteArray()); + } + + public static void main(String[] args) { + System.out.println("OpenSSL avaliable: " + OpenSsl.isAvailable()); + new SimpleChaincode().start(args); + } + +} diff --git a/first-network/scripts/script.sh b/first-network/scripts/script.sh index 1d43a37e..9d92d3e5 100755 --- a/first-network/scripts/script.sh +++ b/first-network/scripts/script.sh @@ -28,6 +28,10 @@ if [ "$LANGUAGE" = "node" ]; then CC_SRC_PATH="/opt/gopath/src/github.com/chaincode/chaincode_example02/node/" fi +if [ "$LANGUAGE" = "java" ]; then + CC_SRC_PATH="/opt/gopath/src/github.com/chaincode/chaincode_example02/java/" +fi + echo "Channel name : "$CHANNEL_NAME # import utils From 9c6aceed38a18fb0d7764c51304efe1383a03595 Mon Sep 17 00:00:00 2001 From: David Enyeart Date: Sun, 16 Sep 2018 23:37:04 -0400 Subject: [PATCH 12/35] [FAB-12022] Fix CI by increasing couchdb timeout Increase retry timeout from 3s to 15s so that initial CLI commands after peers and couchdb come up are successful. Change-Id: Ib5f879bde52395d9f600683da17bf03aff6e05b2 Signed-off-by: David Enyeart --- scripts/Jenkins_Scripts/byfn_eyfn.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/Jenkins_Scripts/byfn_eyfn.sh b/scripts/Jenkins_Scripts/byfn_eyfn.sh index 7785bdd2..186c563e 100755 --- a/scripts/Jenkins_Scripts/byfn_eyfn.sh +++ b/scripts/Jenkins_Scripts/byfn_eyfn.sh @@ -40,9 +40,9 @@ fi echo "############### BYFN,EYFN CUSTOM CHANNEL WITH COUCHDB TEST ##############" echo "#########################################################################" - echo y | ./byfn.sh -m up -c custom-channel-couchdb -s couchdb -t 60 + echo y | ./byfn.sh -m up -c custom-channel-couchdb -s couchdb -t 75 -d 15 err_Check $? custom-channel-couch couchdb - echo y | ./eyfn.sh -m up -c custom-channel-couchdb -s couchdb -t 60 + echo y | ./eyfn.sh -m up -c custom-channel-couchdb -s couchdb -t 75 -d 15 err_Check $? custom-channel-couch echo y | ./eyfn.sh -m down echo From e7a1b76edb5bad96ca6c5cb02b41756b17e542e8 Mon Sep 17 00:00:00 2001 From: Chris Elder Date: Tue, 11 Sep 2018 12:09:07 -0400 Subject: [PATCH 13/35] [FAB-9386] Remove Marbles sample reference to Fauxton Remove marbles sample chaincode references to Fauxton and outdated "data" wrapper. This change also synchronizes the marbles sample chaincode with fabric/examples/marbles02, for example it adds pagination support that is in fabric/examples/marbles02. Change-Id: Ie80c66d7b2f97081d21c5ea889b159e398b64777 Signed-off-by: Chris Elder --- chaincode/marbles02/go/marbles_chaincode.go | 259 ++++++++++++++------ 1 file changed, 181 insertions(+), 78 deletions(-) diff --git a/chaincode/marbles02/go/marbles_chaincode.go b/chaincode/marbles02/go/marbles_chaincode.go index 2921b604..2ed3efd6 100644 --- a/chaincode/marbles02/go/marbles_chaincode.go +++ b/chaincode/marbles02/go/marbles_chaincode.go @@ -1,20 +1,5 @@ /* -Licensed to the Apache Software Foundation (ASF) under one -or more contributor license agreements. See the NOTICE file -distributed with this work for additional information -regarding copyright ownership. The ASF licenses this file -to you under the Apache License, Version 2.0 (the -"License"); you may not use this file except in compliance -with the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, -software distributed under the License is distributed on an -"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -KIND, either express or implied. See the License for the -specific language governing permissions and limitations -under the License. + SPDX-License-Identifier: Apache-2.0 */ // ====CHAINCODE EXECUTION SAMPLES (CLI) ================== @@ -33,8 +18,11 @@ under the License. // peer chaincode query -C myc1 -n marbles -c '{"Args":["getHistoryForMarble","marble1"]}' // Rich Query (Only supported if CouchDB is used as state database): -// peer chaincode query -C myc1 -n marbles -c '{"Args":["queryMarblesByOwner","tom"]}' -// peer chaincode query -C myc1 -n marbles -c '{"Args":["queryMarbles","{\"selector\":{\"owner\":\"tom\"}}"]}' +// peer chaincode query -C myc1 -n marbles -c '{"Args":["queryMarblesByOwner","tom"]}' +// peer chaincode query -C myc1 -n marbles -c '{"Args":["queryMarbles","{\"selector\":{\"owner\":\"tom\"}}"]}' + +// Rich Query with Pagination (Only supported if CouchDB is used as state database): +// peer chaincode query -C myc1 -n marbles -c '{"Args":["queryMarblesWithPagination","{\"selector\":{\"owner\":\"tom\"}}","3",""]}' // INDEXES TO SUPPORT COUCHDB RICH QUERIES // @@ -73,23 +61,15 @@ under the License. // http://127.0.0.1:5984/ // Index for docType, owner. -// Note that docType and owner fields must be prefixed with the "data" wrapper -// -// Index definition for use with Fauxton interface -// {"index":{"fields":["data.docType","data.owner"]},"ddoc":"indexOwnerDoc", "name":"indexOwner","type":"json"} // // Example curl command line to define index in the CouchDB channel_chaincode database -// curl -i -X POST -H "Content-Type: application/json" -d "{\"index\":{\"fields\":[\"data.docType\",\"data.owner\"]},\"name\":\"indexOwner\",\"ddoc\":\"indexOwnerDoc\",\"type\":\"json\"}" http://hostname:port/myc1_marbles/_index +// curl -i -X POST -H "Content-Type: application/json" -d "{\"index\":{\"fields\":[\"docType\",\"owner\"]},\"name\":\"indexOwner\",\"ddoc\":\"indexOwnerDoc\",\"type\":\"json\"}" http://hostname:port/myc1_marbles/_index // // Index for docType, owner, size (descending order). -// Note that docType, owner and size fields must be prefixed with the "data" wrapper -// -// Index definition for use with Fauxton interface -// {"index":{"fields":[{"data.size":"desc"},{"data.docType":"desc"},{"data.owner":"desc"}]},"ddoc":"indexSizeSortDoc", "name":"indexSizeSortDesc","type":"json"} // // Example curl command line to define index in the CouchDB channel_chaincode database -// curl -i -X POST -H "Content-Type: application/json" -d "{\"index\":{\"fields\":[{\"data.size\":\"desc\"},{\"data.docType\":\"desc\"},{\"data.owner\":\"desc\"}]},\"ddoc\":\"indexSizeSortDoc\", \"name\":\"indexSizeSortDesc\",\"type\":\"json\"}" http://hostname:port/myc1_marbles/_index +// curl -i -X POST -H "Content-Type: application/json" -d "{\"index\":{\"fields\":[{\"size\":\"desc\"},{\"docType\":\"desc\"},{\"owner\":\"desc\"}]},\"ddoc\":\"indexSizeSortDoc\", \"name\":\"indexSizeSortDesc\",\"type\":\"json\"}" http://hostname:port/myc1_marbles/_index // Rich Query with index design doc and index name specified (Only supported if CouchDB is used as state database): // peer chaincode query -C myc1 -n marbles -c '{"Args":["queryMarbles","{\"selector\":{\"docType\":\"marble\",\"owner\":\"tom\"}, \"use_index\":[\"_design/indexOwnerDoc\", \"indexOwner\"]}"]}' @@ -164,6 +144,10 @@ func (t *SimpleChaincode) Invoke(stub shim.ChaincodeStubInterface) pb.Response { return t.getHistoryForMarble(stub, args) } else if function == "getMarblesByRange" { //get marbles based on range query return t.getMarblesByRange(stub, args) + } else if function == "getMarblesByRangeWithPagination" { + return t.getMarblesByRangeWithPagination(stub, args) + } else if function == "queryMarblesWithPagination" { + return t.queryMarblesWithPagination(stub, args) } fmt.Println("invoke did not find func: " + function) //error @@ -360,6 +344,59 @@ func (t *SimpleChaincode) transferMarble(stub shim.ChaincodeStubInterface, args return shim.Success(nil) } +// =========================================================================================== +// constructQueryResponseFromIterator constructs a JSON array containing query results from +// a given result iterator +// =========================================================================================== +func constructQueryResponseFromIterator(resultsIterator shim.StateQueryIteratorInterface) (*bytes.Buffer, error) { + // buffer is a JSON array containing QueryResults + var buffer bytes.Buffer + buffer.WriteString("[") + + bArrayMemberAlreadyWritten := false + for resultsIterator.HasNext() { + queryResponse, err := resultsIterator.Next() + if err != nil { + return nil, err + } + // Add a comma before array members, suppress it for the first array member + if bArrayMemberAlreadyWritten == true { + buffer.WriteString(",") + } + buffer.WriteString("{\"Key\":") + buffer.WriteString("\"") + buffer.WriteString(queryResponse.Key) + buffer.WriteString("\"") + + buffer.WriteString(", \"Record\":") + // Record is a JSON object, so we write as-is + buffer.WriteString(string(queryResponse.Value)) + buffer.WriteString("}") + bArrayMemberAlreadyWritten = true + } + buffer.WriteString("]") + + return &buffer, nil +} + +// =========================================================================================== +// addPaginationMetadataToQueryResults adds QueryResponseMetadata, which contains pagination +// info, to the constructed query results +// =========================================================================================== +func addPaginationMetadataToQueryResults(buffer *bytes.Buffer, responseMetadata *pb.QueryResponseMetadata) *bytes.Buffer { + + buffer.WriteString("[{\"ResponseMetadata\":{\"RecordsCount\":") + buffer.WriteString("\"") + buffer.WriteString(fmt.Sprintf("%v", responseMetadata.FetchedRecordsCount)) + buffer.WriteString("\"") + buffer.WriteString(", \"Bookmark\":") + buffer.WriteString("\"") + buffer.WriteString(responseMetadata.Bookmark) + buffer.WriteString("\"}}]") + + return buffer +} + // =========================================================================================== // getMarblesByRange performs a range query based on the start and end keys provided. @@ -386,32 +423,10 @@ func (t *SimpleChaincode) getMarblesByRange(stub shim.ChaincodeStubInterface, ar } defer resultsIterator.Close() - // buffer is a JSON array containing QueryResults - var buffer bytes.Buffer - buffer.WriteString("[") - - bArrayMemberAlreadyWritten := false - for resultsIterator.HasNext() { - queryResponse, err := resultsIterator.Next() - if err != nil { - return shim.Error(err.Error()) - } - // Add a comma before array members, suppress it for the first array member - if bArrayMemberAlreadyWritten == true { - buffer.WriteString(",") - } - buffer.WriteString("{\"Key\":") - buffer.WriteString("\"") - buffer.WriteString(queryResponse.Key) - buffer.WriteString("\"") - - buffer.WriteString(", \"Record\":") - // Record is a JSON object, so we write as-is - buffer.WriteString(string(queryResponse.Value)) - buffer.WriteString("}") - bArrayMemberAlreadyWritten = true + buffer, err := constructQueryResponseFromIterator(resultsIterator) + if err != nil { + return shim.Error(err.Error()) } - buffer.WriteString("]") fmt.Printf("- getMarblesByRange queryResult:\n%s\n", buffer.String()) @@ -554,38 +569,126 @@ func getQueryResultForQueryString(stub shim.ChaincodeStubInterface, queryString } defer resultsIterator.Close() - // buffer is a JSON array containing QueryRecords - var buffer bytes.Buffer - buffer.WriteString("[") - - bArrayMemberAlreadyWritten := false - for resultsIterator.HasNext() { - queryResponse, err := resultsIterator.Next() - if err != nil { - return nil, err - } - // Add a comma before array members, suppress it for the first array member - if bArrayMemberAlreadyWritten == true { - buffer.WriteString(",") - } - buffer.WriteString("{\"Key\":") - buffer.WriteString("\"") - buffer.WriteString(queryResponse.Key) - buffer.WriteString("\"") - - buffer.WriteString(", \"Record\":") - // Record is a JSON object, so we write as-is - buffer.WriteString(string(queryResponse.Value)) - buffer.WriteString("}") - bArrayMemberAlreadyWritten = true + buffer, err := constructQueryResponseFromIterator(resultsIterator) + if err != nil { + return nil, err } - buffer.WriteString("]") fmt.Printf("- getQueryResultForQueryString queryResult:\n%s\n", buffer.String()) return buffer.Bytes(), nil } +// ====== Pagination ========================================================================= +// Pagination provides a method to retrieve records with a defined pagesize and +// start point (bookmark). An empty string bookmark defines the first "page" of a query +// result. Paginated queries return a bookmark that can be used in +// the next query to retrieve the next page of results. Paginated queries extend +// rich queries and range queries to include a pagesize and bookmark. +// +// Two examples are provided in this example. The first is getMarblesByRangeWithPagination +// which executes a paginated range query. +// The second example is a paginated query for rich ad-hoc queries. +// ========================================================================================= + +// ====== Example: Pagination with Range Query =============================================== +// getMarblesByRangeWithPagination performs a range query based on the start & end key, +// page size and a bookmark. + +// The number of fetched records will be equal to or lesser than the page size. +// Paginated range queries are only valid for read only transactions. +// =========================================================================================== +func (t *SimpleChaincode) getMarblesByRangeWithPagination(stub shim.ChaincodeStubInterface, args []string) pb.Response { + + if len(args) < 4 { + return shim.Error("Incorrect number of arguments. Expecting 4") + } + + startKey := args[0] + endKey := args[1] + //return type of ParseInt is int64 + pageSize, err := strconv.ParseInt(args[2], 10, 32) + if err != nil { + return shim.Error(err.Error()) + } + bookmark := args[3] + + resultsIterator, responseMetadata, err := stub.GetStateByRangeWithPagination(startKey, endKey, int32(pageSize), bookmark) + if err != nil { + return shim.Error(err.Error()) + } + defer resultsIterator.Close() + + buffer, err := constructQueryResponseFromIterator(resultsIterator) + if err != nil { + return shim.Error(err.Error()) + } + + bufferWithPaginationInfo := addPaginationMetadataToQueryResults(buffer, responseMetadata) + + fmt.Printf("- getMarblesByRange queryResult:\n%s\n", bufferWithPaginationInfo.String()) + + return shim.Success(buffer.Bytes()) +} + +// ===== Example: Pagination with Ad hoc Rich Query ======================================================== +// queryMarblesWithPagination uses a query string, page size and a bookmark to perform a query +// for marbles. Query string matching state database syntax is passed in and executed as is. +// The number of fetched records would be equal to or lesser than the specified page size. +// Supports ad hoc queries that can be defined at runtime by the client. +// If this is not desired, follow the queryMarblesForOwner example for parameterized queries. +// Only available on state databases that support rich query (e.g. CouchDB) +// Paginated queries are only valid for read only transactions. +// ========================================================================================= +func (t *SimpleChaincode) queryMarblesWithPagination(stub shim.ChaincodeStubInterface, args []string) pb.Response { + + // 0 + // "queryString" + if len(args) < 3 { + return shim.Error("Incorrect number of arguments. Expecting 3") + } + + queryString := args[0] + //return type of ParseInt is int64 + pageSize, err := strconv.ParseInt(args[1], 10, 32) + if err != nil { + return shim.Error(err.Error()) + } + bookmark := args[2] + + queryResults, err := getQueryResultForQueryStringWithPagination(stub, queryString, int32(pageSize), bookmark) + if err != nil { + return shim.Error(err.Error()) + } + return shim.Success(queryResults) +} + +// ========================================================================================= +// getQueryResultForQueryStringWithPagination executes the passed in query string with +// pagination info. Result set is built and returned as a byte array containing the JSON results. +// ========================================================================================= +func getQueryResultForQueryStringWithPagination(stub shim.ChaincodeStubInterface, queryString string, pageSize int32, bookmark string) ([]byte, error) { + + fmt.Printf("- getQueryResultForQueryString queryString:\n%s\n", queryString) + + resultsIterator, responseMetadata, err := stub.GetQueryResultWithPagination(queryString, pageSize, bookmark) + if err != nil { + return nil, err + } + defer resultsIterator.Close() + + buffer, err := constructQueryResponseFromIterator(resultsIterator) + if err != nil { + return nil, err + } + + bufferWithPaginationInfo := addPaginationMetadataToQueryResults(buffer, responseMetadata) + + fmt.Printf("- getQueryResultForQueryString queryResult:\n%s\n", bufferWithPaginationInfo.String()) + + return buffer.Bytes(), nil +} + func (t *SimpleChaincode) getHistoryForMarble(stub shim.ChaincodeStubInterface, args []string) pb.Response { if len(args) < 1 { From 9ee57c6c2299022ba033f55898c2875cb487eece Mon Sep 17 00:00:00 2001 From: Surya Date: Fri, 7 Sep 2018 12:20:37 -0400 Subject: [PATCH 14/35] [FAB-11778] Upgrade to v1.3.x from v1.2.x in byfn Changes include upgrade from v1.2.x to v1.3.x. First, upgrades the network from v1.2.x to v1.3.x and upgrade_to_v13.sh will run config updates on /Channel level and /Channel/Application level for v1_3 capabilities. Add 15 sec's delay to couchdb tests Change-Id: Ic2a1633842b7dd8a39ee674c5159d67b46122ff4 Signed-off-by: Surya Signed-off-by: RameshBabu --- first-network/byfn.sh | 106 ++++++++------- first-network/configtx.yaml | 125 ++++++++++++++++-- first-network/scripts/capabilities.json | 4 +- .../{upgrade_to_v12.sh => upgrade_to_v13.sh} | 57 ++++++-- 4 files changed, 215 insertions(+), 77 deletions(-) rename first-network/scripts/{upgrade_to_v12.sh => upgrade_to_v13.sh} (68%) diff --git a/first-network/byfn.sh b/first-network/byfn.sh index 04439046..41ed1b8a 100755 --- a/first-network/byfn.sh +++ b/first-network/byfn.sh @@ -41,7 +41,7 @@ function printHelp() { echo " - 'down' - clear the network with docker-compose down" echo " - 'restart' - restart the network" echo " - 'generate' - generate required certificates and genesis block" - echo " - 'upgrade' - upgrade the network from version 1.1.x to 1.2.x" + echo " - 'upgrade' - upgrade the network from version 1.2.x to 1.3.x" echo " -c - channel name to use (defaults to \"mychannel\")" echo " -t - CLI timeout duration in seconds (defaults to 10)" echo " -d - delay duration in seconds (defaults to 3)" @@ -172,62 +172,66 @@ function networkUp() { fi } -# Upgrade the network components which are at version 1.1.x to 1.2.x +# Upgrade the network components which are at version 1.2.x to 1.3.x # Stop the orderer and peers, backup the ledger for orderer and peers, cleanup chaincode containers and images # and relaunch the orderer and peers with latest tag function upgradeNetwork() { - docker inspect -f '{{.Config.Volumes}}' orderer.example.com | grep -q '/var/hyperledger/production/orderer' - if [ $? -ne 0 ]; then - echo "ERROR !!!! This network does not appear to be using volumes for its ledgers, did you start from fabric-samples >= v1.1.x?" - exit 1 - fi + if [[ "$IMAGETAG" == *"1.3"* ]] || [[ $IMAGETAG == "latest" ]]; then + docker inspect -f '{{.Config.Volumes}}' orderer.example.com | grep -q '/var/hyperledger/production/orderer' + if [ $? -ne 0 ]; then + echo "ERROR !!!! This network does not appear to be using volumes for its ledgers, did you start from fabric-samples >= v1.2.x?" + exit 1 + fi - LEDGERS_BACKUP=./ledgers-backup + LEDGERS_BACKUP=./ledgers-backup - # create ledger-backup directory - mkdir -p $LEDGERS_BACKUP + # create ledger-backup directory + mkdir -p $LEDGERS_BACKUP - export IMAGE_TAG=$IMAGETAG - if [ "${IF_COUCHDB}" == "couchdb" ]; then - COMPOSE_FILES="-f $COMPOSE_FILE -f $COMPOSE_FILE_COUCH" + export IMAGE_TAG=$IMAGETAG + if [ "${IF_COUCHDB}" == "couchdb" ]; then + COMPOSE_FILES="-f $COMPOSE_FILE -f $COMPOSE_FILE_COUCH" + else + COMPOSE_FILES="-f $COMPOSE_FILE" + fi + + # removing the cli container + docker-compose $COMPOSE_FILES stop cli + docker-compose $COMPOSE_FILES up -d --no-deps cli + + echo "Upgrading orderer" + docker-compose $COMPOSE_FILES stop orderer.example.com + docker cp -a orderer.example.com:/var/hyperledger/production/orderer $LEDGERS_BACKUP/orderer.example.com + docker-compose $COMPOSE_FILES up -d --no-deps orderer.example.com + + for PEER in peer0.org1.example.com peer1.org1.example.com peer0.org2.example.com peer1.org2.example.com; do + echo "Upgrading peer $PEER" + + # Stop the peer and backup its ledger + docker-compose $COMPOSE_FILES stop $PEER + docker cp -a $PEER:/var/hyperledger/production $LEDGERS_BACKUP/$PEER/ + + # Remove any old containers and images for this peer + CC_CONTAINERS=$(docker ps | grep dev-$PEER | awk '{print $1}') + if [ -n "$CC_CONTAINERS" ]; then + docker rm -f $CC_CONTAINERS + fi + CC_IMAGES=$(docker images | grep dev-$PEER | awk '{print $1}') + if [ -n "$CC_IMAGES" ]; then + docker rmi -f $CC_IMAGES + fi + + # Start the peer again + docker-compose $COMPOSE_FILES up -d --no-deps $PEER + done + + docker exec cli scripts/upgrade_to_v13.sh $CHANNEL_NAME $CLI_DELAY $LANGUAGE $CLI_TIMEOUT $VERBOSE + if [ $? -ne 0 ]; then + echo "ERROR !!!! Test failed" + exit 1 + fi else - COMPOSE_FILES="-f $COMPOSE_FILE" - fi - - # removing the cli container - docker-compose $COMPOSE_FILES stop cli - docker-compose $COMPOSE_FILES up -d --no-deps cli - - echo "Upgrading orderer" - docker-compose $COMPOSE_FILES stop orderer.example.com - docker cp -a orderer.example.com:/var/hyperledger/production/orderer $LEDGERS_BACKUP/orderer.example.com - docker-compose $COMPOSE_FILES up -d --no-deps orderer.example.com - - for PEER in peer0.org1.example.com peer1.org1.example.com peer0.org2.example.com peer1.org2.example.com; do - echo "Upgrading peer $PEER" - - # Stop the peer and backup its ledger - docker-compose $COMPOSE_FILES stop $PEER - docker cp -a $PEER:/var/hyperledger/production $LEDGERS_BACKUP/$PEER/ - - # Remove any old containers and images for this peer - CC_CONTAINERS=$(docker ps | grep dev-$PEER | awk '{print $1}') - if [ -n "$CC_CONTAINERS" ]; then - docker rm -f $CC_CONTAINERS - fi - CC_IMAGES=$(docker images | grep dev-$PEER | awk '{print $1}') - if [ -n "$CC_IMAGES" ]; then - docker rmi -f $CC_IMAGES - fi - - # Start the peer again - docker-compose $COMPOSE_FILES up -d --no-deps $PEER - done - - docker exec cli scripts/upgrade_to_v12.sh $CHANNEL_NAME $CLI_DELAY $LANGUAGE $CLI_TIMEOUT $VERBOSE - if [ $? -ne 0 ]; then - echo "ERROR !!!! Test failed" - exit 1 + echo "ERROR !!!! Pass the v1.3.x image tag" fi } @@ -528,7 +532,7 @@ elif [ "${MODE}" == "generate" ]; then ## Generate Artifacts elif [ "${MODE}" == "restart" ]; then ## Restart the network networkDown networkUp -elif [ "${MODE}" == "upgrade" ]; then ## Upgrade the network from version 1.1.x to 1.2.x +elif [ "${MODE}" == "upgrade" ]; then ## Upgrade the network from version 1.2.x to 1.3.x upgradeNetwork else printHelp diff --git a/first-network/configtx.yaml b/first-network/configtx.yaml index e55efb05..24826c07 100644 --- a/first-network/configtx.yaml +++ b/first-network/configtx.yaml @@ -27,6 +27,20 @@ Organizations: # MSPDir is the filesystem path which contains the MSP configuration MSPDir: crypto-config/ordererOrganizations/example.com/msp + # Policies defines the set of policies at this level of the config tree + # For organization policies, their canonical path is usually + # /Channel/// + Policies: + Readers: + Type: Signature + Rule: "OR('OrdererMSP.member')" + Writers: + Type: Signature + Rule: "OR('OrdererMSP.member')" + Admins: + Type: Signature + Rule: "OR('OrdererMSP.admin')" + - &Org1 # DefaultOrg defines the organization which is used in the sampleconfig # of the fabric.git development environment @@ -37,6 +51,21 @@ Organizations: MSPDir: crypto-config/peerOrganizations/org1.example.com/msp + # Policies defines the set of policies at this level of the config tree + # For organization policies, their canonical path is usually + # /Channel/// + Policies: + Readers: + Type: Signature + Rule: "OR('Org1MSP.admin', 'Org1MSP.peer', 'Org1MSP.client')" + Writers: + Type: Signature + Rule: "OR('Org1MSP.admin', 'Org1MSP.client')" + Admins: + Type: Signature + Rule: "OR('Org1MSP.admin')" + + # leave this flag set to true. AnchorPeers: # AnchorPeers defines the location of peers which can be used # for cross org gossip communication. Note, this value is only @@ -54,6 +83,20 @@ Organizations: MSPDir: crypto-config/peerOrganizations/org2.example.com/msp + # Policies defines the set of policies at this level of the config tree + # For organization policies, their canonical path is usually + # /Channel/// + Policies: + Readers: + Type: Signature + Rule: "OR('Org2MSP.admin', 'Org2MSP.peer', 'Org2MSP.client')" + Writers: + Type: Signature + Rule: "OR('Org2MSP.admin', 'Org2MSP.client')" + Admins: + Type: Signature + Rule: "OR('Org2MSP.admin')" + AnchorPeers: # AnchorPeers defines the location of peers which can be used # for cross org gossip communication. Note, this value is only @@ -84,11 +127,11 @@ Capabilities: # Channel capabilities apply to both the orderers and the peers and must be # supported by both. Set the value of the capability to true to require it. Global: &ChannelCapabilities - # V1.1 for Global is a catchall flag for behavior which has been - # determined to be desired for all orderers and peers running v1.0.x, + # V1.3 for Channel is a catchall flag for behavior which has been + # determined to be desired for all orderers and peers running < v1.3.0, # but the modification of which would cause incompatibilities. Users # should leave this flag set to true. - V1_1: true + V1_3: true # Orderer capabilities apply only to the orderers, and may be safely # manipulated without concern for upgrading peers. Set the value of the @@ -104,11 +147,9 @@ Capabilities: # manipulated without concern for upgrading orderers. Set the value of the # capability to true to require it. Application: &ApplicationCapabilities - # V1.2 for Application is a catchall flag for behavior which has been - # determined to be desired for all peers running v1.0.x, but the - # modification of which would cause incompatibilities. Users should - # leave this flag set to true. - V1_2: true + # V1.2 for Application enables the new non-backwards compatible + # features and fixes of fabric v1.3 + V1_3: true ################################################################################ # @@ -124,6 +165,20 @@ Application: &ApplicationDefaults # the application side of the network Organizations: + # Policies defines the set of policies at this level of the config tree + # For Application policies, their canonical path is + # /Channel/Application/ + Policies: + Readers: + Type: ImplicitMeta + Rule: "ANY Readers" + Writers: + Type: ImplicitMeta + Rule: "ANY Writers" + Admins: + Type: ImplicitMeta + Rule: "MAJORITY Admins" + ################################################################################ # # SECTION: Orderer @@ -169,6 +224,57 @@ Orderer: &OrdererDefaults # the orderer side of the network Organizations: + # Policies defines the set of policies at this level of the config tree + # For Orderer policies, their canonical path is + # /Channel/Orderer/ + Policies: + Readers: + Type: ImplicitMeta + Rule: "ANY Readers" + Writers: + Type: ImplicitMeta + Rule: "ANY Writers" + Admins: + Type: ImplicitMeta + Rule: "MAJORITY Admins" + # BlockValidation specifies what signatures must be included in the block + # from the orderer for the peer to validate it. + BlockValidation: + Type: ImplicitMeta + Rule: "ANY Writers" + +################################################################################ +# +# CHANNEL +# +# This section defines the values to encode into a config transaction or +# genesis block for channel related parameters. +# +################################################################################ +Channel: &ChannelDefaults + # Policies defines the set of policies at this level of the config tree + # For Channel policies, their canonical path is + # /Channel/ + Policies: + # Who may invoke the 'Deliver' API + Readers: + Type: ImplicitMeta + Rule: "ANY Readers" + # Who may invoke the 'Broadcast' API + Writers: + Type: ImplicitMeta + Rule: "ANY Writers" + # By default, who may modify elements at this config level + Admins: + Type: ImplicitMeta + Rule: "MAJORITY Admins" + + # Capabilities describes the channel level capabilities, see the + # dedicated Capabilities section elsewhere in this file for a full + # description + Capabilities: + <<: *ChannelCapabilities + ################################################################################ # # Profile @@ -180,8 +286,7 @@ Orderer: &OrdererDefaults Profiles: TwoOrgsOrdererGenesis: - Capabilities: - <<: *ChannelCapabilities + <<: *ChannelDefaults Orderer: <<: *OrdererDefaults Organizations: diff --git a/first-network/scripts/capabilities.json b/first-network/scripts/capabilities.json index 3acfab99..5c3f3e0e 100644 --- a/first-network/scripts/capabilities.json +++ b/first-network/scripts/capabilities.json @@ -2,8 +2,8 @@ "mod_policy": "Admins", "value": { "capabilities": { - "V1_2": {} + "V1_3": {} } }, "version": "0" -} \ No newline at end of file +} diff --git a/first-network/scripts/upgrade_to_v12.sh b/first-network/scripts/upgrade_to_v13.sh similarity index 68% rename from first-network/scripts/upgrade_to_v12.sh rename to first-network/scripts/upgrade_to_v13.sh index 79d4600a..905cec1b 100755 --- a/first-network/scripts/upgrade_to_v12.sh +++ b/first-network/scripts/upgrade_to_v13.sh @@ -7,7 +7,7 @@ echo "\___ \ | | / _ \ | |_) | | | " echo " ___) | | | / ___ \ | _ < | | " echo "|____/ |_| /_/ \_\ |_| \_\ |_| " echo -echo "Upgrade your first network (BYFN) from v1.1.x to v1.2.x end-to-end test" +echo "Upgrade your first network (BYFN) from v1.2.x to v1.3.x end-to-end test" echo CHANNEL_NAME="$1" DELAY="$2" @@ -48,19 +48,35 @@ addCapabilityToChannel() { # Modify the correct section of the config based on capabilities group if [ $GROUP == "application" ]; then jq -s '.[0] * {"channel_group":{"groups":{"Application": {"values": {"Capabilities": .[1]}}}}}' config.json ./scripts/capabilities.json >modified_config.json + elif [ $GROUP == "channel" ]; then + jq -s '.[0] * {"channel_group":{"values": {"Capabilities": .[1]}}}' config.json ./scripts/capabilities.json > modified_config.json fi # Create a config updated for this channel based on the differences between config.json and modified_config.json # write the output to config_update_in_envelope.pb createConfigUpdate "$CH_NAME" config.json modified_config.json config_update_in_envelope.pb - # Sign, and set the correct identity for submission. - if [ $GROUP == "application" ]; then - # Modifying the application group requires a majority of application admins to sign. - # Sign with PeerOrg1.Admin - signConfigtxAsPeerOrg 1 config_update_in_envelope.pb - # Prepare to sign the update as the PeerOrg2.Admin - setGlobals 0 2 + if [ $CH_NAME != "testchainid" ] ; then + # Sign, and set the correct identity for submission. + if [ $GROUP == "application" ]; then + # Modifying the application group requires a majority of application admins to sign. + # Sign with PeerOrg1.Admin + signConfigtxAsPeerOrg 1 config_update_in_envelope.pb + # Prepare to sign the update as the PeerOrg2.Admin + setGlobals 0 2 + elif [ $GROUP == "channel" ]; then + # Modifying the channel group requires a majority of application admins and the orderer admin to sign. + # Sign with PeerOrg1.Admin + signConfigtxAsPeerOrg 1 config_update_in_envelope.pb + # Sign with PeerOrg2.Admin + signConfigtxAsPeerOrg 2 config_update_in_envelope.pb + # Prepare to sign the update as the OrdererOrg.Admin + setOrdererGlobals + fi + else + # For the orderer system channel, only the orderer admin needs sign + # which will be attached during the update + setOrdererGlobals fi if [ -z "$CORE_PEER_TLS_ENABLED" -o "$CORE_PEER_TLS_ENABLED" = "false" ]; then @@ -78,6 +94,23 @@ addCapabilityToChannel() { echo "===================== Config update for \"$GROUP\" on \"$CH_NAME\" is completed ===================== " } +sleep $DELAY + +#Config update for /Channel for testchainid +echo "Config update for /Channel on \"testchainid\"" +addCapabilityToChannel testchainid channel + +sleep $DELAY + +#Config update for /Channel +echo "Config update for /Channel on \"$CHANNEL_NAME\"" +addCapabilityToChannel "$CHANNEL_NAME" channel + +sleep $DELAY + +#Query on chaincode on Peer0/Org1 +echo "Querying chaincode on org1/peer0..." +chaincodeQuery 0 1 90 sleep $DELAY @@ -87,13 +120,9 @@ addCapabilityToChannel "$CHANNEL_NAME" application sleep $DELAY -#Query on chaincode on Peer0/Org1 -echo "Querying chaincode on org1/peer0..." -chaincodeQuery 0 1 90 - #Invoke on chaincode on Peer0/Org1 echo "Sending invoke transaction on org1/peer0..." -chaincodeInvoke 0 1 +chaincodeInvoke 0 1 0 2 sleep $DELAY @@ -103,7 +132,7 @@ chaincodeQuery 0 1 80 ##Invoke on chaincode on Peer0/Org2 echo "Sending invoke transaction on org2/peer0..." -chaincodeInvoke 0 2 +chaincodeInvoke 0 2 0 1 sleep $DELAY From 40897861b0bf2836ad4db9af1f18a3bce33166f7 Mon Sep 17 00:00:00 2001 From: Anthony O'Dowd Date: Wed, 5 Sep 2018 07:47:44 +0100 Subject: [PATCH 15/35] FAB-11867 Develop Apps:Sample pt 2 -- application Change-Id: I0897682a00be1f6ebaf8eee090872c5057dc3fba Signed-off-by: Anthony O'Dowd --- commercial-paper/application/application.js | 76 ++++++ .../gateway/connectionProfile.yaml | 225 ++++++++++++++++++ commercial-paper/contract/lib/ledgerutils.js | 88 +++++++ commercial-paper/contract/lib/paper.js | 117 +++++++++ .../contract/lib/papercontract.js | 138 +++++++++++ 5 files changed, 644 insertions(+) create mode 100644 commercial-paper/application/application.js create mode 100644 commercial-paper/application/gateway/connectionProfile.yaml create mode 100644 commercial-paper/contract/lib/ledgerutils.js create mode 100644 commercial-paper/contract/lib/paper.js create mode 100644 commercial-paper/contract/lib/papercontract.js diff --git a/commercial-paper/application/application.js b/commercial-paper/application/application.js new file mode 100644 index 00000000..af11620c --- /dev/null +++ b/commercial-paper/application/application.js @@ -0,0 +1,76 @@ +/* +SPDX-License-Identifier: Apache-2.0 +*/ + +/* + * This application has 6 basic steps: + * 1. Select an identity from a wallet + * 2. Connect to network gateway + * 3. Access PaperNet network + * 4. Construct request to issue commercial paper + * 5. Submit transaction + * 6. Process response + */ + +'use strict'; + +// Bring key classes into scope, most importantly Fabric SDK network class +const file = require("fs"); +const yaml = require('js-yaml'); +const { FileSystemWallet, Gateway } = require('fabric-network'); +const { CommercialPaper } = require('./paper.js'); + +// A wallet stores a collection of identities for use +const wallet = new FileSystemWallet('./wallet'); + +// A gateway defines the peers used to access Fabric networks +const gateway = new Gateway(); + +// Main try/catch/finally block +try { + + // Load connection profile; will be used to locate a gateway + connectionProfile = yaml.safeLoad(file.readFileSync('./gateway/connectionProfile.yaml', 'utf8')); + + // Set connection options; use 'admin' identity from application wallet + let connectionOptions = { + identity: 'isabella.the.issuer@magnetocorp.com', + wallet: wallet, + commitTimeout: 100, + strategy: MSPID_SCOPE_ANYFORTX, + commitNotifyStrategy: WAIT_FOR_ALL_CHANNEL_PEER + } + + // Connect to gateway using application specified parameters + await gateway.connect(connectionProfile, connectionOptions); + + console.log('Connected to Fabric gateway.') + + // Get addressability to PaperNet network + const network = await gateway.getNetwork('PaperNet'); + + // Get addressability to commercial paper contract + const contract = await network.getContract('papercontract', 'org.papernet.commercialpaper'); + + console.log('Submit commercial paper issue transaction.') + + // issue commercial paper + const response = await contract.submitTransaction('issue', 'MagnetoCorp', '00001', '2020-05-31', '2020-11-30', '5000000'); + + let paper = CommercialPaper.deserialize(response); + + console.log(`${paper.issuer} commercial paper : ${paper.paperNumber} successfully issued for value ${paper.faceValue}`); + + console.log('Transaction complete.') + +} catch (error) { + + console.log(`Error processing transaction. ${error}`); + +} finally { + + // Disconnect from the gateway + console.log('Disconnect from Fabric gateway.') + gateway.disconnect(); + +} \ No newline at end of file diff --git a/commercial-paper/application/gateway/connectionProfile.yaml b/commercial-paper/application/gateway/connectionProfile.yaml new file mode 100644 index 00000000..9c6115cc --- /dev/null +++ b/commercial-paper/application/gateway/connectionProfile.yaml @@ -0,0 +1,225 @@ +--- +# +# The network connection profile provides client applications the information about the target +# blockchain network that are necessary for the applications to interact with it. These are all +# knowledge that must be acquired from out-of-band sources. This file provides such a source. +# +name: "global-trade-network" + +# +# Any properties with an "x-" prefix will be treated as application-specific, exactly like how naming +# in HTTP headers or swagger properties work. The SDK will simply ignore these fields and leave +# them for the applications to process. This is a mechanism for different components of an application +# to exchange information that are not part of the standard schema described below. In particular, +# the "x-type" property with the "hlfv1" value example below is used by Hyperledger Composer to +# determine the type of Fabric networks (v0.6 vs. v1.0) it needs to work with. +# +x-type: "hlfv1" + +# +# Describe what the target network is/does. +# +description: "The network to be in if you want to stay in the global trade business" + +# +# Schema version of the content. Used by the SDK to apply the corresponding parsing rules. +# +version: "1.0" + +# +# The client section is SDK-specific. The sample below is for the node.js SDK +# +#client: + # Which organization does this application instance belong to? The value must be the name of an org + # defined under "organizations" + #organization: Org1 + + # Some SDKs support pluggable KV stores, the properties under "credentialStore" + # are implementation specific + #credentialStore: + # [Optional]. Specific to FileKeyValueStore.js or similar implementations in other SDKs. Can be others + # if using an alternative impl. For instance, CouchDBKeyValueStore.js would require an object + # here for properties like url, db name, etc. + #path: "/tmp/hfc-kvs" + + # [Optional]. Specific to the CryptoSuite implementation. Software-based implementations like + # CryptoSuite_ECDSA_AES.js in node SDK requires a key store. PKCS#11 based implementations does + # not. + #cryptoStore: + # Specific to the underlying KeyValueStore that backs the crypto key store. + #path: "/tmp/hfc-cvs" + + # [Optional]. Specific to Composer environment + #wallet: wallet-name + +# +# [Optional]. But most apps would have this section so that channel objects can be constructed +# based on the content below. If an app is creating channels, then it likely will not need this +# section. +# +channels: + # name of the channel + PaperNet: + # Required. list of orderers designated by the application to use for transactions on this + # channel. This list can be a result of access control ("org1" can only access "ordererA"), or + # operational decisions to share loads from applications among the orderers. The values must + # be "names" of orgs defined under "organizations/peers" + orderers: + - orderer.example.com + + # Required. list of peers from participating orgs + peers: + peer1.magnetocorp.com: + # [Optional]. will this peer be sent transaction proposals for endorsement? The peer must + # have the chaincode installed. The app can also use this property to decide which peers + # to send the chaincode install request. Default: true + endorsingPeer: true + + # [Optional]. will this peer be sent query proposals? The peer must have the chaincode + # installed. The app can also use this property to decide which peers to send the + # chaincode install request. Default: true + chaincodeQuery: true + + # [Optional]. will this peer be sent query proposals that do not require chaincodes, like + # queryBlock(), queryTransaction(), etc. Default: true + ledgerQuery: true + + # [Optional]. will this peer be the target of the SDK's listener registration? All peers can + # produce events but the app typically only needs to connect to one to listen to events. + # Default: true + eventSource: true + + peer2.digibank.com: + endorsingPeer: true + chaincodeQuery: false + ledgerQuery: true + eventSource: true + + # [Optional]. what chaincodes are expected to exist on this channel? The application can use + # this information to validate that the target peers are in the expected state by comparing + # this list with the query results of getInstalledChaincodes() and getInstantiatedChaincodes() + chaincodes: + # the format follows the "cannonical name" of chaincodes by fabric code + - example02:v1 + - marbles:1.0 + +# +# list of participating organizations in this network +# +organizations: + Org1: + mspid: magnetocorpMSP + + peers: + - peer1.magnetocorp.com + + # [Optional]. Certificate Authorities issue certificates for identification purposes in a Fabric based + # network. Typically certificates provisioning is done in a separate process outside of the + # runtime network. Fabric-CA is a special certificate authority that provides a REST APIs for + # dynamic certificate management (enroll, revoke, re-enroll). The following section is only for + # Fabric-CA servers. + certificateAuthorities: + - ca-org1 + + # [Optional]. If the application is going to make requests that are reserved to organization + # administrators, including creating/updating channels, installing/instantiating chaincodes, it + # must have access to the admin identity represented by the private key and signing certificate. + # Both properties can be the PEM string or local path to the PEM file. Note that this is mainly for + # convenience in development mode, production systems should not expose sensitive information + # this way. The SDK should allow applications to set the org admin identity via APIs, and only use + # this route as an alternative when it exists. + adminPrivateKey: + path: test/fixtures/channel/crypto-config/peerOrganizations/org1.example.com/users/Admin@org1.example.com/keystore/9022d671ceedbb24af3ea69b5a8136cc64203df6b9920e26f48123fcfcb1d2e9_sk + signedCert: + path: test/fixtures/channel/crypto-config/peerOrganizations/org1.example.com/users/Admin@org1.example.com/signcerts/Admin@org1.example.com-cert.pem + + # the profile will contain public information about organizations other than the one it belongs to. + # These are necessary information to make transaction lifecycles work, including MSP IDs and + # peers with a public URL to send transaction proposals. The file will not contain private + # information reserved for members of the organization, such as admin key and certificate, + # fabric-ca registrar enroll ID and secret, etc. + Org2: + mspid: digibankMSP + peers: + - peer1.digibank.com + certificateAuthorities: + - ca-org2 + adminPrivateKey: + path: test/fixtures/channel/crypto-config/peerOrganizations/org2.example.com/users/Admin@org2.example.com/keystore/5a983ddcbefe52a7f9b8ee5b85a590c3e3a43c4ccd70c7795bec504e7f74848d_sk + signedCert: + path: test/fixtures/channel/crypto-config/peerOrganizations/org2.example.com/users/Admin@org2.example.com/signcerts/Admin@org2.example.com-cert.pem + +# +# List of orderers to send transaction and channel create/update requests to. For the time +# being only one orderer is needed. If more than one is defined, which one get used by the +# SDK is implementation specific. Consult each SDK's documentation for its handling of orderers. +# +orderers: + orderer.example.com: + url: grpcs://localhost:7050 + + # these are standard properties defined by the gRPC library + # they will be passed in as-is to gRPC client constructor + grpcOptions: + ssl-target-name-override: orderer.example.com + + tlsCACerts: + path: test/fixtures/channel/crypto-config/ordererOrganizations/example.com/orderers/orderer.example.com/tlscacerts/example.com-cert.pem + +# +# List of peers to send various requests to, including endorsement, query +# and event listener registration. +# +peers: + peer1.magnetocorp.com: + # this URL is used to send endorsement and query requests + url: grpcs://localhost:7051 + + grpcOptions: + ssl-target-name-override: peer1.magnetocorp.com + request-timeout: 120 + + tlsCACerts: + path: certificates/magnetocorp/magnetocorp.com-cert.pem + + peer1.digibank.com: + url: grpcs://localhost:8051 + grpcOptions: + ssl-target-name-override: peer1.digibank.com + tlsCACerts: + path: certificates/digibank/digibank.com-cert.pem + +# +# Fabric-CA is a special kind of Certificate Authority provided by Hyperledger Fabric which allows +# certificate management to be done via REST APIs. Application may choose to use a standard +# Certificate Authority instead of Fabric-CA, in which case this section would not be specified. +# +certificateAuthorities: + ca-org1: + url: https://localhost:7054 + # the properties specified under this object are passed to the 'http' client verbatim when + # making the request to the Fabric-CA server + httpOptions: + verify: false + tlsCACerts: + path: test/fixtures/channel/crypto-config/peerOrganizations/org1.example.com/ca/org1.example.com-cert.pem + + # Fabric-CA supports dynamic user enrollment via REST APIs. A "root" user, a.k.a registrar, is + # needed to enroll and invoke new users. + registrar: + - enrollId: admin + enrollSecret: adminpw + # [Optional] The optional name of the CA. + caName: ca-org1 + + ca-org2: + url: https://localhost:8054 + httpOptions: + verify: false + tlsCACerts: + path: test/fixtures/channel/crypto-config/peerOrganizations/org2.example.com/ca/org2.example.com-cert.pem + registrar: + - enrollId: admin + enrollSecret: adminpw + # [Optional] The optional name of the CA. + caName: ca-org2 \ No newline at end of file diff --git a/commercial-paper/contract/lib/ledgerutils.js b/commercial-paper/contract/lib/ledgerutils.js new file mode 100644 index 00000000..b18f60ea --- /dev/null +++ b/commercial-paper/contract/lib/ledgerutils.js @@ -0,0 +1,88 @@ +/* +SPDX-License-Identifier: Apache-2.0 +*/ + +'use strict'; + +/** + * Utility class for data, object mapulation, e.g. serialization + */ +class Utils { + + /** + * Convert object to buffer containing JSON data serialization + * Typically used before putState()ledger API + * @param {Object} JSON object to serialize + * @return {buffer} buffer with the data to store + */ + static serialize(object) { + return Buffer.from(JSON.stringify(object)); + } + + /** + * Deserialize object, i.e. Covert serialized data to JSON object + * Typically used after getState() ledger API + * @param {data} data to deserialize into JSON object + * @return {json} json with the data to store + */ + static deserialize(data) { + return JSON.parse(data); + } +} + +/** + * StateList provides a named virtual container for a set of ledger states. + * Each state has a unique key which associates it with the container, rather + * than the container containing a link to the state. This minimizes collisions + * for parallel transactions on different states. + */ +class StateList { + + /** + * Store Fabric context for subsequent API access, and name of list + */ + constructor(ctx, listName) { + this.ctx = ctx; + this.name = listName; + } + + /** + * Add a state to the list. Creates a new state in worldstate with + * appropriate composite key. Note that state defines its own key. + * State object is serialized before writing. + */ + async addState(state) { + let key = this.ctx.stub.createCompositeKey(this.name, [state.getKey()]); + let data = Utils.serialize(state); + await this.ctx.stub.putState(key, data); + } + + /** + * Get a state from the list using supplied keys. Form composite + * keys to retrieve state from world state. State data is deserialized + * into JSON object before being returned. + */ + async getState([keys]) { + let key = this.ctx.stub.createCompositeKey(this.name, [keys]); + let data = await this.ctx.stub.getState(key); + let state = Utils.deserialize(data); + return state; + } + + /** + * Update a state in the list. Puts the new state in world state with + * appropriate composite key. Note that state defines its own key. + * A state is serialized before writing. Logic is very similar to + * addState() but kept separate becuase it is semantically distinct. + */ + async updateState(state) { + let key = this.ctx.stub.createCompositeKey(this.name, [state.getKey()]); + let data = Utils.serialize(state); + await this.ctx.stub.putState(key, data); + } + +} + +module.exports = { + StateList +}; diff --git a/commercial-paper/contract/lib/paper.js b/commercial-paper/contract/lib/paper.js new file mode 100644 index 00000000..db770cfb --- /dev/null +++ b/commercial-paper/contract/lib/paper.js @@ -0,0 +1,117 @@ +/* +SPDX-License-Identifier: Apache-2.0 +*/ + +'use strict'; + +// Enumerate commercial paper state values +const cpState = { + ISSUED: 1, + TRADING: 2, + REDEEMED: 3 +}; + +/** + * State class. States have a type, unique key, and a lifecycle current state + */ +class State { + constructor(type, [keyParts]) { + this.type = JSON.stringify(type); + this.key = makeKey([keyParts]); + this.currentState = null; + } + + getType() { + return this.type; + } + + static makeKey([keyParts]) { + return keyParts.map(part => JSON.stringify(part)).join(''); + } + + getKey() { + return this.key; + } + +} + +/** + * CommercialPaper class extends State class + * Class will be used by application and smart contract to define a paper + */ +class CommercialPaper extends State { + + constructor(issuer, paperNumber, issueDateTime, maturityDateTime, faceValue) { + super(`org.papernet.commercialpaper`, [issuer, paperNumber]); + + this.issuer = issuer; + this.paperNumber = paperNumber; + this.owner = issuer; + this.issueDateTime = issueDateTime; + this.maturityDateTime = maturityDateTime; + this.faceValue = faceValue; + } + + /** + * Basic getters and setters + */ + getIssuer() { + return this.issuer; + } + + setIssuer(newIssuer) { + this.issuer = newIssuer; + } + + getOwner() { + return this.owner; + } + + setOwner(newOwner) { + this.owner = newOwner; + } + + /** + * Useful methods to encapsulate commercial paper states + */ + setIssued() { + this.currentState = cpState.ISSUED; + } + + setTrading() { + this.currentState = cpState.TRADING; + } + + setRedeemed() { + this.currentState = cpState.REDEEMED; + } + + isIssued() { + return this.currentState === cpState.ISSUED; + } + + isTrading() { + return this.currentState === cpState.TRADING; + } + + isRedeemed() { + return this.currentState === cpState.REDEEMED; + } + + /** + * Serialize/deserialize commercial paper + **/ + + serialize() { + return Buffer.from(JSON.stringify(this)); + } + + static deserialize(data) { + return Object.create(new CommercialPaper, JSON.parse(data)); + } + +} + +module.exports = { + CommercialPaper, +}; diff --git a/commercial-paper/contract/lib/papercontract.js b/commercial-paper/contract/lib/papercontract.js new file mode 100644 index 00000000..a4963279 --- /dev/null +++ b/commercial-paper/contract/lib/papercontract.js @@ -0,0 +1,138 @@ +/* +SPDX-License-Identifier: Apache-2.0 +*/ + +'use strict'; + +// Fabric smart contract classes +const { Contract, Context } = require('fabric-contract-api'); + +// PaperNet specifc classes +const { CommercialPaper } = require('./paper.js'); + +// Utility classes +const { StateList } = require('./ledgerutils.js'); + +/** + * Define custom context for commercial paper by extending Fabric Context class + */ +class CommericalPaperContext extends Context { + + constructor() { + // All papers held ins a list of Fabric states + this.cpList = new StateList(this, 'org.papernet.commercialpaperlist'); + } + +} + +/** + * Define commercial paper smart contract by extending Fabric Contract class + */ +class CommercialPaperContract extends Contract { + + constructor() { + // Unique namespace when multiple contracts per chaincode file + super('org.papernet.commercialpaper'); + } + + // This method is called when a smart contract is instantiated + // Often used to set up the ledger main transactions are called + instantiate() { + + } + + // A custom context provides easy access to the list of commercial papers + createContext() { + return new CommericalPaperContext(); + } + + /** + * Issue commercial paper + * @param {TxContext} ctx the transaction context + * @param {String} issuer commercial paper issuer + * @param {Integer} paperNumber paper number for this issuer + * @param {String} issueDateTime paper issue date + * @param {String} maturityDateTime paper maturity date + * @param {Integer} faceValue face value of paper + */ + async issue(ctx, issuer, paperNumber, issueDateTime, maturityDateTime, faceValue) { + + let cp = new CommercialPaper(issuer, paperNumber, issueDateTime, maturityDateTime, faceValue); + + // Smart contract, rather than paper, moves paper into ISSUED state + cp.setIssued(); + + // Add the paper to the list of all similar commercial papers in the ledger world state + await ctx.cpList.addState(cp); + + return cp.serialize(); + } + + /** + * Buy commercial paper + * @param {TxContext} ctx the transaction context + * @param {String} issuer commercial paper issuer + * @param {Integer} paperNumber paper number for this issuer + * @param {String} currentOwner current owner of paper + * @param {String} newOwner new owner of paper + * @param {Integer} price price paid for this paper + * @param {String} purchaseDateTime time paper was purchased (i.e. traded) + */ + async buy(ctx, issuer, paperNumber, currentOwner, newOwner, price, purchaseDateTime) { + + let cpKey = CommercialPaper.makeKey([issuer, paperNumber]); + + let cp = await ctx.cpList.getState(cpKey); + + if (cp.getOwner() !== currentOwner) { + throw new Error('Paper ' + issuer + paperNumber + ' is not owned by ' + currentOwner); + } + // First buy moves state from ISSUED to TRADING + if (cp.isIssued()) { + cp.setTrading(); + } + // Check paper is not already REDEEMED + if (cp.IsTrading()) { + cp.setOwner(newOwner); + } else { + throw new Error('Paper ' + issuer + paperNumber + ' is not trading. Current state = ' + cp.getCurrentState()); + } + + await ctx.cpList.updateState(cp); + return cp.deserialize(); + } + + /** + * Redeem commercial paper + * @param {TxContext} ctx the transaction context + * @param {String} issuer commercial paper issuer + * @param {Integer} paperNumber paper number for this issuer + * @param {String} redeemingOwner redeeming owner of paper + * @param {String} redeemDateTime time paper was redeemed + */ + async redeem(ctx, issuer, paperNumber, redeemingOwner, redeemDateTime) { + + let cpKey = CommercialPaper.makeKey([issuer, paperNumber]); + + let cp = await ctx.cpList.getState(cpKey); + + // Check paper is TRADING, not REDEEMED + if (cp.IsRedeemed()) { + throw new Error('Paper ' + issuer + paperNumber + ' already redeemed'); + } + + // Verify that the redeemer owns the commercial paper before redeeming it + if (cp.getOwner() === redeemingOwner) { + cp.setOwner(cp.getIssuer()); + cp.setRedeemed(); + } else { + throw new Error('Redeeming owner does not own paper' + issuer + paperNumber); + } + + await ctx.cpList.updateState(cp); + return cp.serialize(); + } + +} + +module.exports = CommericalPaperContract; From f62952f980cf47d31d53ab3cbc6b9617026fa6b4 Mon Sep 17 00:00:00 2001 From: Keith Smith Date: Sat, 15 Sep 2018 13:39:27 -0400 Subject: [PATCH 16/35] [FABC-131] Change fabric-ca sample to build images Since fabric-ca-orderer/peer/tools images are no longer being published, this updates the fabric-ca sample to not use them. Instead, it either uses locally built images or it builds them by using curl to download the published fabric-ca-client binary from nexus. Change-Id: I29776c72445660ab02a5e82a4e6b0ade0d0167e7 Signed-off-by: Keith Smith Signed-off-by: Saad Karim --- fabric-ca/.gitignore | 3 +++ fabric-ca/README.md | 38 +++++++++++++++++------------ fabric-ca/bootstrap.sh | 24 ------------------ fabric-ca/makeDocker.sh | 54 ++++++++++++++++++++++++++++++++++++++--- fabric-ca/start.sh | 9 ++++++- 5 files changed, 85 insertions(+), 43 deletions(-) delete mode 100755 fabric-ca/bootstrap.sh diff --git a/fabric-ca/.gitignore b/fabric-ca/.gitignore index a5a77b45..d21ef6d8 100644 --- a/fabric-ca/.gitignore +++ b/fabric-ca/.gitignore @@ -1,2 +1,5 @@ docker-compose.yml +fabric-ca-orderer.dockerfile +fabric-ca-peer.dockerfile +fabric-ca-tools.dockerfile data diff --git a/fabric-ca/README.md b/fabric-ca/README.md index d704faa9..398fa7d0 100755 --- a/fabric-ca/README.md +++ b/fabric-ca/README.md @@ -18,23 +18,31 @@ The Hyperledger Fabric CA sample demonstrates the following: ## Running this sample -1. The following images are required to run this sample: -*hyperledger/fabric-ca-orderer*, *hyperledger/fabric-ca-peer*, and *hyperledger/fabric-ca-tools* - - #### install the images - Run the *bootstrap.sh* script provided with this sample to download the - required images for fabric-ca sample. For the v1.2.0-rc1 release, you - will need to specify the version as follows: - - ``` - bootstrap.sh 1.2.0-rc1 - ``` - -2. To run this sample, simply run the *start.sh* script. You may do this +1. To run this sample, simply run the *start.sh* script. You may do this multiple times in a row as needed since the *start.sh* script cleans up before -starting each time. +starting each time. This sample can be run with the latest released version, +an older released version, or from locally built docker images as follows: -3. To stop the containers which are started by the *start.sh* script, you may run the *stop.sh* script. + a. By default, the sample is run with the latest released version of Fabric + and Fabric CA. + + b. Older versions of Fabric and Fabric CA can be used by setting the + `FABRIC_TAG` environment variable. For example, `export FABRIC_TAG=1.2.0` + will run the sample with 1.2.0 version of Fabric and Fabric CA. + + c. The sample can also be run with locally built Fabric and Fabric CA + docker images. Fabric and Fabric CA repositories must be cloned with following + commands: + + `git clone https://github.com/hyperledger/fabric.git` + `git clone https://github.com/hyperledger/fabric-ca.git` + + Then execute the `make docker-all` command from the fabric-ca repository. This will + build the necessary images based on the local source code. Before executing the + *start.sh* script, set the `FABRIC_TAG` environment variable to 'local' as follows: + `export FABRIC_TAG=local`. + +2. To stop the containers which are started by the *start.sh* script, you may run the *stop.sh* script. ## Understanding this sample diff --git a/fabric-ca/bootstrap.sh b/fabric-ca/bootstrap.sh deleted file mode 100755 index ad096e24..00000000 --- a/fabric-ca/bootstrap.sh +++ /dev/null @@ -1,24 +0,0 @@ -#!/bin/bash -# -# Copyright IBM Corp. All Rights Reserved. -# -# SPDX-License-Identifier: Apache-2.0 -# - -# current version of fabric-ca released -export CA_TAG=${1:-1.2.0} - -dockerCaPull() { - echo "==> FABRIC CA IMAGE" - echo - for image in "" "-tools" "-orderer" "-peer"; do - docker pull hyperledger/fabric-ca${image}:$CA_TAG - docker tag hyperledger/fabric-ca${image}:$CA_TAG hyperledger/fabric-ca${image} - done -} - -echo "===> Pulling fabric ca Image" -dockerCaPull ${CA_TAG} - -echo "===> List out hyperledger docker images" -docker images | grep hyperledger/fabric-ca diff --git a/fabric-ca/makeDocker.sh b/fabric-ca/makeDocker.sh index f55bbba4..51b744fe 100755 --- a/fabric-ca/makeDocker.sh +++ b/fabric-ca/makeDocker.sh @@ -9,11 +9,24 @@ # This script builds the docker compose file needed to run this sample. # +# IMPORTANT: The following default FABRIC_TAG value should be updated for each +# release after the fabric-orderer and fabric-peer images have been published +# for the release. +export FABRIC_TAG=${FABRIC_TAG:-1.2.0} + +export FABRIC_CA_TAG=${FABRIC_CA_TAG:-${FABRIC_TAG}} +export NS=${NS:-hyperledger} + +export ARCH="linux-amd64" # Docker images run on linux +CA_BINARY_FILE=hyperledger-fabric-ca-${ARCH}-${FABRIC_CA_TAG}.tar.gz +URL=https://nexus.hyperledger.org/content/repositories/releases/org/hyperledger/fabric-ca/hyperledger-fabric-ca/${ARCH}-${FABRIC_CA_TAG}/${CA_BINARY_FILE} + SDIR=$(dirname "$0") source $SDIR/scripts/env.sh function main { { + createDockerFiles writeHeader writeRootFabricCA if $USE_INTERMEDIATE_CA; then @@ -26,6 +39,41 @@ function main { log "Created docker-compose.yml" } +# Create various dockerfiles used by this sample +function createDockerFiles { + if [ "$FABRIC_TAG" = "local" ]; then + ORDERER_BUILD="image: hyperledger/fabric-ca-orderer" + PEER_BUILD="image: hyperledger/fabric-ca-peer" + TOOLS_BUILD="image: hyperledger/fabric-ca-tools" + else + createDockerFile orderer + ORDERER_BUILD="build: + context: . + dockerfile: fabric-ca-orderer.dockerfile" + createDockerFile peer + PEER_BUILD="build: + context: . + dockerfile: fabric-ca-peer.dockerfile" + createDockerFile tools + TOOLS_BUILD="build: + context: . + dockerfile: fabric-ca-tools.dockerfile" + fi +} + +# createDockerFile +function createDockerFile { + { + echo "FROM ${NS}/fabric-${1}:${FABRIC_TAG}" + echo 'RUN apt-get update && apt-get install -y netcat jq && apt-get install -y curl && rm -rf /var/cache/apt' + echo "RUN curl -o /tmp/fabric-ca-client.tar.gz $URL && tar -xzvf /tmp/fabric-ca-client.tar.gz -C /tmp && cp /tmp/bin/fabric-ca-client /usr/local/bin" + echo 'RUN chmod +x /usr/local/bin/fabric-ca-client' + echo 'ARG FABRIC_CA_DYNAMIC_LINK=false' + # libraries needed when image is built dynamically + echo 'RUN if [ "\$FABRIC_CA_DYNAMIC_LINK" = "true" ]; then apt-get install -y libltdl-dev; fi' + } > $SDIR/fabric-ca-${1}.dockerfile +} + # Write services for the root fabric CA servers function writeRootFabricCA { for ORG in $ORGS; do @@ -46,7 +94,7 @@ function writeIntermediateFabricCA { function writeSetupFabric { echo " setup: container_name: setup - image: hyperledger/fabric-ca-tools + $TOOLS_BUILD command: /bin/bash -c '/scripts/setup-fabric.sh 2>&1 | tee /$SETUP_LOGFILE; sleep 99999' volumes: - ./scripts:/scripts @@ -173,7 +221,7 @@ function writeOrderer { MYHOME=/etc/hyperledger/orderer echo " $ORDERER_NAME: container_name: $ORDERER_NAME - image: hyperledger/fabric-ca-orderer + $ORDERER_BUILD environment: - FABRIC_CA_CLIENT_HOME=$MYHOME - FABRIC_CA_CLIENT_TLS_CERTFILES=$CA_CHAINFILE @@ -210,7 +258,7 @@ function writePeer { MYHOME=/opt/gopath/src/github.com/hyperledger/fabric/peer echo " $PEER_NAME: container_name: $PEER_NAME - image: hyperledger/fabric-ca-peer + $PEER_BUILD environment: - FABRIC_CA_CLIENT_HOME=$MYHOME - FABRIC_CA_CLIENT_TLS_CERTFILES=$CA_CHAINFILE diff --git a/fabric-ca/start.sh b/fabric-ca/start.sh index 34dbeb18..973dfb20 100755 --- a/fabric-ca/start.sh +++ b/fabric-ca/start.sh @@ -8,6 +8,13 @@ # # This script does everything required to run the fabric CA sample. # +# By default, this test is run with the latest released docker images. +# +# To run against a specific fabric/fabric-ca version: +# export FABRIC_TAG=1.2.0 +# +# To run with locally built images: +# export FABRIC_TAG=local set -e @@ -54,7 +61,7 @@ tail -f ${SDIR}/${RUN_SUMFILE}& TAIL_PID=$! # Wait for the run container to complete -while true; do +while true; do if [ -f ${SDIR}/${RUN_SUCCESS_FILE} ]; then kill -9 $TAIL_PID exit 0 From eece3d893b31c12928978529c4630ce6be83fbd7 Mon Sep 17 00:00:00 2001 From: rameshthoomu Date: Sun, 23 Sep 2018 11:40:37 -0400 Subject: [PATCH 17/35] FAB-12106 Update fabric-ca build scripts Update fabric-ca build scripts to download s390x binary to run the fabric-ca test scripts Change-Id: Ieaeac4a7e43435dbf49e6b9dc2649705e9348892 Signed-off-by: rameshthoomu --- fabric-ca/makeDocker.sh | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/fabric-ca/makeDocker.sh b/fabric-ca/makeDocker.sh index 51b744fe..3e2feae9 100755 --- a/fabric-ca/makeDocker.sh +++ b/fabric-ca/makeDocker.sh @@ -16,10 +16,9 @@ export FABRIC_TAG=${FABRIC_TAG:-1.2.0} export FABRIC_CA_TAG=${FABRIC_CA_TAG:-${FABRIC_TAG}} export NS=${NS:-hyperledger} - -export ARCH="linux-amd64" # Docker images run on linux -CA_BINARY_FILE=hyperledger-fabric-ca-${ARCH}-${FABRIC_CA_TAG}.tar.gz -URL=https://nexus.hyperledger.org/content/repositories/releases/org/hyperledger/fabric-ca/hyperledger-fabric-ca/${ARCH}-${FABRIC_CA_TAG}/${CA_BINARY_FILE} +export MARCH=$(echo "$(uname -s|tr '[:upper:]' '[:lower:]'|sed 's/mingw64_nt.*/windows/')-$(uname -m | sed 's/x86_64/amd64/g')" | awk '{print tolower($0)}') +CA_BINARY_FILE=hyperledger-fabric-ca-${MARCH}-${FABRIC_CA_TAG}.tar.gz +URL=https://nexus.hyperledger.org/content/repositories/releases/org/hyperledger/fabric-ca/hyperledger-fabric-ca/${MARCH}-${FABRIC_CA_TAG}/${CA_BINARY_FILE} SDIR=$(dirname "$0") source $SDIR/scripts/env.sh From 3237229184948fa509120cba67fb7982e4b03c4b Mon Sep 17 00:00:00 2001 From: Jonathan Blood Date: Thu, 20 Sep 2018 14:43:09 +0100 Subject: [PATCH 18/35] [FAB-12073] Fix Org3 peers CouchDB config. Change-Id: I279a32b3a07a326fc0291f259f66b4f3a036a58a Signed-off-by: Jonathan Blood --- first-network/docker-compose-couch-org3.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/first-network/docker-compose-couch-org3.yaml b/first-network/docker-compose-couch-org3.yaml index 03e57ac8..4e98ad94 100644 --- a/first-network/docker-compose-couch-org3.yaml +++ b/first-network/docker-compose-couch-org3.yaml @@ -27,7 +27,7 @@ services: peer0.org3.example.com: environment: - CORE_LEDGER_STATE_STATEDATABASE=CouchDB - - CORE_LEDGER_STATE_COUCHDBCONFIG_COUCHDBADDRESS=couchdb0:5984 + - CORE_LEDGER_STATE_COUCHDBCONFIG_COUCHDBADDRESS=couchdb4:5984 # The CORE_LEDGER_STATE_COUCHDBCONFIG_USERNAME and CORE_LEDGER_STATE_COUCHDBCONFIG_PASSWORD # provide the credentials for ledger to connect to CouchDB. The username and password must # match the username and password set for the associated CouchDB. @@ -54,7 +54,7 @@ services: peer1.org3.example.com: environment: - CORE_LEDGER_STATE_STATEDATABASE=CouchDB - - CORE_LEDGER_STATE_COUCHDBCONFIG_COUCHDBADDRESS=couchdb1:5984 + - CORE_LEDGER_STATE_COUCHDBCONFIG_COUCHDBADDRESS=couchdb5:5984 # The CORE_LEDGER_STATE_COUCHDBCONFIG_USERNAME and CORE_LEDGER_STATE_COUCHDBCONFIG_PASSWORD # provide the credentials for ledger to connect to CouchDB. The username and password must # match the username and password set for the associated CouchDB. From 9f80e47d2d72e70890434ebafa153a9d5266e218 Mon Sep 17 00:00:00 2001 From: gennady Date: Mon, 24 Sep 2018 11:50:58 +0300 Subject: [PATCH 19/35] [FAB-12119] Fix groupId in java chaincodes According to sonatype.org naming requirements, java shim jars groupId should be org.hyperledger.fabric-chaincode-java Change-Id: Ia30cb77b1081b3fb4f7573568f2e2abfe89315d4 Signed-off-by: gennady --- chaincode/chaincode_example02/java/build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/chaincode/chaincode_example02/java/build.gradle b/chaincode/chaincode_example02/java/build.gradle index 1f45bcdd..932a25b1 100644 --- a/chaincode/chaincode_example02/java/build.gradle +++ b/chaincode/chaincode_example02/java/build.gradle @@ -8,7 +8,7 @@ plugins { id 'java' } -group 'org.hyperledger.fabric' +group 'org.hyperledger.fabric-chaincode-java' version '1.0-SNAPSHOT' sourceCompatibility = 1.8 @@ -19,7 +19,7 @@ repositories { } dependencies { - compile group: 'org.hyperledger.fabric', name: 'fabric-chaincode-shim', version: '1.3.0-SNAPSHOT' + compile group: 'org.hyperledger.fabric-chaincode-java', name: 'fabric-chaincode-shim', version: '1.3.0-SNAPSHOT' testCompile group: 'junit', name: 'junit', version: '4.12' } From 514d4560d93c013f7c0d22a0ff639dc8ed2ceed7 Mon Sep 17 00:00:00 2001 From: David Enyeart Date: Wed, 26 Sep 2018 00:39:26 -0400 Subject: [PATCH 20/35] [FAB-12170] Fix dependency check in java chaincode Currently sample java chaincode can only work with version 1.3.0-SNAPSHOT of the shim. Allow sample java chaincode to work with any v1.x java shim. Change-Id: Iee69289392b4fa5fdb5cb14c41672f96120f711f Signed-off-by: David Enyeart --- chaincode/chaincode_example02/java/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/chaincode/chaincode_example02/java/build.gradle b/chaincode/chaincode_example02/java/build.gradle index 932a25b1..5221272c 100644 --- a/chaincode/chaincode_example02/java/build.gradle +++ b/chaincode/chaincode_example02/java/build.gradle @@ -19,7 +19,7 @@ repositories { } dependencies { - compile group: 'org.hyperledger.fabric-chaincode-java', name: 'fabric-chaincode-shim', version: '1.3.0-SNAPSHOT' + compile group: 'org.hyperledger.fabric-chaincode-java', name: 'fabric-chaincode-shim', version: '1.+' testCompile group: 'junit', name: 'junit', version: '4.12' } From edee6387f1d5bb80395db7be2800eb3156e41743 Mon Sep 17 00:00:00 2001 From: David Enyeart Date: Wed, 26 Sep 2018 13:12:40 -0400 Subject: [PATCH 21/35] [FAB-12184] Prepare fabric-samples for 1.3.0-rc1 Change-Id: I791a7dc50557547036209dbabb5a6c42ee2e0c38 Signed-off-by: David Enyeart --- README.md | 4 ++-- fabric-ca/README.md | 4 ++-- fabric-ca/makeDocker.sh | 2 +- fabric-ca/start.sh | 2 +- first-network/configtx.yaml | 42 ++++++++++++++++++++++++------------- scripts/bootstrap.sh | 8 +++---- 6 files changed, 37 insertions(+), 25 deletions(-) diff --git a/README.md b/README.md index fbefa729..02e28279 100644 --- a/README.md +++ b/README.md @@ -9,11 +9,11 @@ intend to use to ensure alignment. ## Download Binaries and Docker Images -The [`scripts/bootstrap.sh`](https://github.com/hyperledger/fabric-samples/blob/release-1.2/scripts/bootstrap.sh) +The [`scripts/bootstrap.sh`](https://github.com/hyperledger/fabric-samples/blob/release-1.3/scripts/bootstrap.sh) script will preload all of the requisite docker images for Hyperledger Fabric and tag them with the 'latest' tag. Optionally, specify a version for fabric, fabric-ca and thirdparty images. Default versions -are 1.2.0, 1.2.0 and 0.4.10 respectively. +are 1.3.0-rc1, 1.3.0-rc1 and 0.4.12 respectively. ```bash ./scripts/bootstrap.sh [version] [ca version] [thirdparty_version] diff --git a/fabric-ca/README.md b/fabric-ca/README.md index 398fa7d0..d9166c1c 100755 --- a/fabric-ca/README.md +++ b/fabric-ca/README.md @@ -27,8 +27,8 @@ an older released version, or from locally built docker images as follows: and Fabric CA. b. Older versions of Fabric and Fabric CA can be used by setting the - `FABRIC_TAG` environment variable. For example, `export FABRIC_TAG=1.2.0` - will run the sample with 1.2.0 version of Fabric and Fabric CA. + `FABRIC_TAG` environment variable. For example, `export FABRIC_TAG=1.3.0-rc1` + will run the sample with 1.3.0-rc1 version of Fabric and Fabric CA. c. The sample can also be run with locally built Fabric and Fabric CA docker images. Fabric and Fabric CA repositories must be cloned with following diff --git a/fabric-ca/makeDocker.sh b/fabric-ca/makeDocker.sh index 3e2feae9..b0313521 100755 --- a/fabric-ca/makeDocker.sh +++ b/fabric-ca/makeDocker.sh @@ -12,7 +12,7 @@ # IMPORTANT: The following default FABRIC_TAG value should be updated for each # release after the fabric-orderer and fabric-peer images have been published # for the release. -export FABRIC_TAG=${FABRIC_TAG:-1.2.0} +export FABRIC_TAG=${FABRIC_TAG:-1.3.0-rc1} export FABRIC_CA_TAG=${FABRIC_CA_TAG:-${FABRIC_TAG}} export NS=${NS:-hyperledger} diff --git a/fabric-ca/start.sh b/fabric-ca/start.sh index 973dfb20..298a0d47 100755 --- a/fabric-ca/start.sh +++ b/fabric-ca/start.sh @@ -11,7 +11,7 @@ # By default, this test is run with the latest released docker images. # # To run against a specific fabric/fabric-ca version: -# export FABRIC_TAG=1.2.0 +# export FABRIC_TAG=1.3.0-rc1 # # To run with locally built images: # export FABRIC_TAG=local diff --git a/first-network/configtx.yaml b/first-network/configtx.yaml index 24826c07..9990a736 100644 --- a/first-network/configtx.yaml +++ b/first-network/configtx.yaml @@ -125,31 +125,43 @@ Organizations: ################################################################################ Capabilities: # Channel capabilities apply to both the orderers and the peers and must be - # supported by both. Set the value of the capability to true to require it. - Global: &ChannelCapabilities + # supported by both. + # Set the value of the capability to true to require it. + Channel: &ChannelCapabilities # V1.3 for Channel is a catchall flag for behavior which has been - # determined to be desired for all orderers and peers running < v1.3.0, - # but the modification of which would cause incompatibilities. Users - # should leave this flag set to true. + # determined to be desired for all orderers and peers running at the v1.3.x + # level, but which would be incompatible with orderers and peers from + # prior releases. + # Prior to enabling V1.3 channel capabilities, ensure that all + # orderers and peers on a channel are at v1.3.0 or later. V1_3: true # Orderer capabilities apply only to the orderers, and may be safely - # manipulated without concern for upgrading peers. Set the value of the - # capability to true to require it. + # used with prior release peers. + # Set the value of the capability to true to require it. Orderer: &OrdererCapabilities - # V1.1 for Order is a catchall flag for behavior which has been - # determined to be desired for all orderers running v1.0.x, but the - # modification of which would cause incompatibilities. Users should - # leave this flag set to true. + # V1.1 for Orderer is a catchall flag for behavior which has been + # determined to be desired for all orderers running at the v1.1.x + # level, but which would be incompatible with orderers from prior releases. + # Prior to enabling V1.1 orderer capabilities, ensure that all + # orderers on a channel are at v1.1.0 or later. V1_1: true # Application capabilities apply only to the peer network, and may be safely - # manipulated without concern for upgrading orderers. Set the value of the - # capability to true to require it. + # used with prior release orderers. + # Set the value of the capability to true to require it. Application: &ApplicationCapabilities - # V1.2 for Application enables the new non-backwards compatible - # features and fixes of fabric v1.3 + # V1.3 for Application enables the new non-backwards compatible + # features and fixes of fabric v1.3. V1_3: true + # V1.2 for Application enables the new non-backwards compatible + # features and fixes of fabric v1.2 (note, this need not be set if + # later version capabilities are set) + V1_2: false + # V1.1 for Application enables the new non-backwards compatible + # features and fixes of fabric v1.1 (note, this need not be set if + # later version capabilities are set). + V1_1: false ################################################################################ # diff --git a/scripts/bootstrap.sh b/scripts/bootstrap.sh index 96c6da31..769a111f 100755 --- a/scripts/bootstrap.sh +++ b/scripts/bootstrap.sh @@ -6,11 +6,11 @@ # # if version not passed in, default to latest released version -export VERSION=1.2.0 +export VERSION=1.3.0-rc1 # if ca version not passed in, default to latest released version export CA_VERSION=$VERSION # current version of thirdparty images (couchdb, kafka and zookeeper) released -export THIRDPARTY_IMAGE_VERSION=0.4.10 +export THIRDPARTY_IMAGE_VERSION=0.4.12 export ARCH=$(echo "$(uname -s|tr '[:upper:]' '[:lower:]'|sed 's/mingw64_nt.*/windows/')-$(uname -m | sed 's/x86_64/amd64/g')") export MARCH=$(uname -m) @@ -32,8 +32,8 @@ printHelp() { echo "-d - bypass docker image download" echo "-b - bypass download of platform-specific binaries" echo - echo "e.g. bootstrap.sh 1.2.0 1.2.0 0.4.10" - echo "would download docker images and binaries for version 1.2.0 (fabric) 1.2.0 (fabric-ca) 0.4.10 (thirdparty)" + echo "e.g. bootstrap.sh 1.3.0-rc1 1.3.0-rc1 0.4.12" + echo "would download docker images and binaries for version 1.3.0-rc1 (fabric) 1.3.0-rc1 (fabric-ca) 0.4.12 (thirdparty)" } dockerFabricPull() { From 33d333fd46f8a68cf78557582f474f9e7004029b Mon Sep 17 00:00:00 2001 From: rameshthoomu Date: Wed, 26 Sep 2018 17:24:07 -0400 Subject: [PATCH 22/35] FAB-12190 Update stable version in CI scripts Update stable version to 1.4.0-stable in CI scripts Change-Id: I558442ccce8975533f9123193d7aa343ae883ba5 Signed-off-by: rameshthoomu --- scripts/Jenkins_Scripts/CI_Script.sh | 4 ++-- scripts/Jenkins_Scripts/byfn_eyfn.sh | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/scripts/Jenkins_Scripts/CI_Script.sh b/scripts/Jenkins_Scripts/CI_Script.sh index 453084a4..ab0d3aca 100755 --- a/scripts/Jenkins_Scripts/CI_Script.sh +++ b/scripts/Jenkins_Scripts/CI_Script.sh @@ -8,10 +8,10 @@ # exit on first error export BASE_FOLDER=$WORKSPACE/gopath/src/github.com/hyperledger -export PROJECT_VERSION=1.3.0-stable +export PROJECT_VERSION=1.4.0-stable export NEXUS_URL=nexus3.hyperledger.org:10001 export ORG_NAME="hyperledger/fabric" -export NODE_VER=8.9.4 # Default nodejs version +export NODE_VER=8.11.3 # Default nodejs version # Fetch baseimage version curl -L https://raw.githubusercontent.com/hyperledger/fabric/master/Makefile > Makefile diff --git a/scripts/Jenkins_Scripts/byfn_eyfn.sh b/scripts/Jenkins_Scripts/byfn_eyfn.sh index 186c563e..103907a5 100755 --- a/scripts/Jenkins_Scripts/byfn_eyfn.sh +++ b/scripts/Jenkins_Scripts/byfn_eyfn.sh @@ -9,7 +9,7 @@ ARCH=$(dpkg --print-architecture) echo "-----------> ARCH" $ARCH MARCH=$(uname -s|tr '[:upper:]' '[:lower:]') echo "-----------> MARCH" $MARCH -VERSION=1.3.0 +VERSION=1.4.0 MVN_METADATA=$(echo "https://nexus.hyperledger.org/content/repositories/releases/org/hyperledger/fabric/hyperledger-fabric-$VERSION-stable/maven-metadata.xml") curl -L "$MVN_METADATA" > maven-metadata.xml RELEASE_TAG=$(cat maven-metadata.xml | grep release) From 4445e8d47ecf4beff2f5052c3800431643e03dd1 Mon Sep 17 00:00:00 2001 From: rameshthoomu Date: Tue, 2 Oct 2018 22:03:37 -0400 Subject: [PATCH 23/35] FAB-12272 Increase MAX_RETRY to 10 This change is to fix the couchdb timeout errors in byfn test. This could be an CI environment issue but to fix CI failures, increasing the MAX_RETRY count to 10 Change-Id: Id16b1846374eb2cb91b4d67fedb38562df90c7d3 Signed-off-by: rameshthoomu --- first-network/scripts/script.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/first-network/scripts/script.sh b/first-network/scripts/script.sh index 9d92d3e5..b720f08b 100755 --- a/first-network/scripts/script.sh +++ b/first-network/scripts/script.sh @@ -21,7 +21,7 @@ VERBOSE="$5" : ${VERBOSE:="false"} LANGUAGE=`echo "$LANGUAGE" | tr [:upper:] [:lower:]` COUNTER=1 -MAX_RETRY=5 +MAX_RETRY=10 CC_SRC_PATH="github.com/chaincode/chaincode_example02/go/" if [ "$LANGUAGE" = "node" ]; then From c6f63241867c448ecc72a04f4d918de3d01bff6d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A1udio=20Ramos?= Date: Tue, 2 Oct 2018 20:52:26 -0300 Subject: [PATCH 24/35] [FAB-12257] allow balance-transfer for doscovery MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Balance-Transfer docker-compose file does not have the parameters -CORE_PEER_GOSSIP_BOOTSTRAP and -CORE_PEER_GOSSIP_EXTERNALENDPOINT assigned to its peers. This impacts the usage of Fabric v1.2 discovery feature by apps like Blockchain Explorer Change-Id: I2ca8adc57af34a0442e91a956b97e754088bba74 Signed-off-by: Cláudio Ramos --- balance-transfer/artifacts/docker-compose.yaml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/balance-transfer/artifacts/docker-compose.yaml b/balance-transfer/artifacts/docker-compose.yaml index c5098077..6443236a 100644 --- a/balance-transfer/artifacts/docker-compose.yaml +++ b/balance-transfer/artifacts/docker-compose.yaml @@ -74,6 +74,8 @@ services: - CORE_PEER_ID=peer0.org1.example.com - CORE_PEER_LOCALMSPID=Org1MSP - CORE_PEER_ADDRESS=peer0.org1.example.com:7051 + - CORE_PEER_GOSSIP_BOOTSTRAP=peer1.org1.example.com:7051 + - CORE_PEER_GOSSIP_EXTERNALENDPOINT=peer0.org1.example.com:7051 ports: - 7051:7051 - 7053:7053 @@ -91,6 +93,8 @@ services: - CORE_PEER_ID=peer1.org1.example.com - CORE_PEER_LOCALMSPID=Org1MSP - CORE_PEER_ADDRESS=peer1.org1.example.com:7051 + - CORE_PEER_GOSSIP_BOOTSTRAP=peer0.org1.example.com:7051 + - CORE_PEER_GOSSIP_EXTERNALENDPOINT=peer1.org1.example.com:7051 ports: - 7056:7051 - 7058:7053 @@ -108,6 +112,8 @@ services: - CORE_PEER_ID=peer0.org2.example.com - CORE_PEER_LOCALMSPID=Org2MSP - CORE_PEER_ADDRESS=peer0.org2.example.com:7051 + - CORE_PEER_GOSSIP_BOOTSTRAP=peer1.org2.example.com:7051 + - CORE_PEER_GOSSIP_EXTERNALENDPOINT=peer0.org2.example.com:7051 ports: - 8051:7051 - 8053:7053 @@ -125,6 +131,8 @@ services: - CORE_PEER_ID=peer1.org2.example.com - CORE_PEER_LOCALMSPID=Org2MSP - CORE_PEER_ADDRESS=peer1.org2.example.com:7051 + - CORE_PEER_GOSSIP_BOOTSTRAP=peer0.org2.example.com:7051 + - CORE_PEER_GOSSIP_EXTERNALENDPOINT=peer1.org2.example.com:7051 ports: - 8056:7051 - 8058:7053 From 3a12c6022b393b95f64481d316e96ab76095425e Mon Sep 17 00:00:00 2001 From: Hui Kang Date: Tue, 2 Oct 2018 23:52:46 -0400 Subject: [PATCH 25/35] [FAB-12275] Fix the warn in creating genesis block - add system channel name Change-Id: Ie36e36b2053524cf3bbcf9be17305ccb7d3f966c Signed-off-by: Hui Kang --- first-network/byfn.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/first-network/byfn.sh b/first-network/byfn.sh index 41ed1b8a..d2eb6592 100755 --- a/first-network/byfn.sh +++ b/first-network/byfn.sh @@ -383,7 +383,7 @@ function generateChannelArtifacts() { # Note: For some unknown reason (at least for now) the block file can't be # named orderer.genesis.block or the orderer will fail to launch! set -x - configtxgen -profile TwoOrgsOrdererGenesis -outputBlock ./channel-artifacts/genesis.block + configtxgen -profile TwoOrgsOrdererGenesis -channelID byfn-sys-channel -outputBlock ./channel-artifacts/genesis.block res=$? set +x if [ $res -ne 0 ]; then From c9251480d575affdc98a040a624c18d0761c08a9 Mon Sep 17 00:00:00 2001 From: David Enyeart Date: Wed, 10 Oct 2018 17:20:24 -0400 Subject: [PATCH 26/35] [FAB-12415] samples for 1.3.0 (master cleanup) fabric-samples already completed in release-1.3 branch. This CR fixes up version references in master to match. Change-Id: I95f9d2db5e5fed749560768ca0ba753bb7cae700 Signed-off-by: David Enyeart --- README.md | 2 +- fabric-ca/README.md | 4 ++-- fabric-ca/makeDocker.sh | 2 +- fabric-ca/start.sh | 2 +- scripts/bootstrap.sh | 8 ++++---- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 02e28279..918a133d 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,7 @@ The [`scripts/bootstrap.sh`](https://github.com/hyperledger/fabric-samples/blob/ script will preload all of the requisite docker images for Hyperledger Fabric and tag them with the 'latest' tag. Optionally, specify a version for fabric, fabric-ca and thirdparty images. Default versions -are 1.3.0-rc1, 1.3.0-rc1 and 0.4.12 respectively. +are 1.3.0, 1.3.0 and 0.4.13 respectively. ```bash ./scripts/bootstrap.sh [version] [ca version] [thirdparty_version] diff --git a/fabric-ca/README.md b/fabric-ca/README.md index d9166c1c..568a198e 100755 --- a/fabric-ca/README.md +++ b/fabric-ca/README.md @@ -27,8 +27,8 @@ an older released version, or from locally built docker images as follows: and Fabric CA. b. Older versions of Fabric and Fabric CA can be used by setting the - `FABRIC_TAG` environment variable. For example, `export FABRIC_TAG=1.3.0-rc1` - will run the sample with 1.3.0-rc1 version of Fabric and Fabric CA. + `FABRIC_TAG` environment variable. For example, `export FABRIC_TAG=1.3.0` + will run the sample with 1.3.0 version of Fabric and Fabric CA. c. The sample can also be run with locally built Fabric and Fabric CA docker images. Fabric and Fabric CA repositories must be cloned with following diff --git a/fabric-ca/makeDocker.sh b/fabric-ca/makeDocker.sh index b0313521..168503fd 100755 --- a/fabric-ca/makeDocker.sh +++ b/fabric-ca/makeDocker.sh @@ -12,7 +12,7 @@ # IMPORTANT: The following default FABRIC_TAG value should be updated for each # release after the fabric-orderer and fabric-peer images have been published # for the release. -export FABRIC_TAG=${FABRIC_TAG:-1.3.0-rc1} +export FABRIC_TAG=${FABRIC_TAG:-1.3.0} export FABRIC_CA_TAG=${FABRIC_CA_TAG:-${FABRIC_TAG}} export NS=${NS:-hyperledger} diff --git a/fabric-ca/start.sh b/fabric-ca/start.sh index 298a0d47..13e994c6 100755 --- a/fabric-ca/start.sh +++ b/fabric-ca/start.sh @@ -11,7 +11,7 @@ # By default, this test is run with the latest released docker images. # # To run against a specific fabric/fabric-ca version: -# export FABRIC_TAG=1.3.0-rc1 +# export FABRIC_TAG=1.3.0 # # To run with locally built images: # export FABRIC_TAG=local diff --git a/scripts/bootstrap.sh b/scripts/bootstrap.sh index 769a111f..b36db883 100755 --- a/scripts/bootstrap.sh +++ b/scripts/bootstrap.sh @@ -6,11 +6,11 @@ # # if version not passed in, default to latest released version -export VERSION=1.3.0-rc1 +export VERSION=1.3.0 # if ca version not passed in, default to latest released version export CA_VERSION=$VERSION # current version of thirdparty images (couchdb, kafka and zookeeper) released -export THIRDPARTY_IMAGE_VERSION=0.4.12 +export THIRDPARTY_IMAGE_VERSION=0.4.13 export ARCH=$(echo "$(uname -s|tr '[:upper:]' '[:lower:]'|sed 's/mingw64_nt.*/windows/')-$(uname -m | sed 's/x86_64/amd64/g')") export MARCH=$(uname -m) @@ -32,8 +32,8 @@ printHelp() { echo "-d - bypass docker image download" echo "-b - bypass download of platform-specific binaries" echo - echo "e.g. bootstrap.sh 1.3.0-rc1 1.3.0-rc1 0.4.12" - echo "would download docker images and binaries for version 1.3.0-rc1 (fabric) 1.3.0-rc1 (fabric-ca) 0.4.12 (thirdparty)" + echo "e.g. bootstrap.sh 1.3.0 1.3.0 0.4.13" + echo "would download docker images and binaries for version 1.3.0 (fabric) 1.3.0 (fabric-ca) 0.4.13 (thirdparty)" } dockerFabricPull() { From df311ce23aa9b9b77e8f9206b0f06d5538bc64d6 Mon Sep 17 00:00:00 2001 From: Yuki Kondo Date: Mon, 8 Oct 2018 23:55:46 +0000 Subject: [PATCH 27/35] [FAB-12173] balance-transfer: Update anchor peers Currently, balance-transfer does not have anchor peer configuration. As a result, users are unable to use private data and can't take advantage of service discovery. This CR adds a function and modifies a test script to update anchor peers at the setup. Change-Id: Icbd7e4eb2e3bbcb187a083e94c616ef4825c5fb4 Signed-off-by: Yuki Kondo --- balance-transfer/app.js | 20 +++ balance-transfer/app/update-anchor-peers.js | 114 ++++++++++++++++++ .../artifacts/channel/Org1MSPanchors.tx | Bin 0 -> 284 bytes .../artifacts/channel/Org2MSPanchors.tx | Bin 0 -> 284 bytes balance-transfer/testAPIs.sh | 24 ++++ 5 files changed, 158 insertions(+) create mode 100644 balance-transfer/app/update-anchor-peers.js create mode 100644 balance-transfer/artifacts/channel/Org1MSPanchors.tx create mode 100644 balance-transfer/artifacts/channel/Org2MSPanchors.tx diff --git a/balance-transfer/app.js b/balance-transfer/app.js index cffddce8..83b1226a 100644 --- a/balance-transfer/app.js +++ b/balance-transfer/app.js @@ -34,6 +34,7 @@ var hfc = require('fabric-client'); var helper = require('./app/helper.js'); var createChannel = require('./app/create-channel.js'); var join = require('./app/join-channel.js'); +var updateAnchorPeers = require('./app/update-anchor-peers.js'); var install = require('./app/install-chaincode.js'); var instantiate = require('./app/instantiate-chaincode.js'); var invoke = require('./app/invoke-transaction.js'); @@ -179,6 +180,25 @@ app.post('/channels/:channelName/peers', async function(req, res) { let message = await join.joinChannel(channelName, peers, req.username, req.orgname); res.send(message); }); +// Update anchor peers +app.post('/channels/:channelName/anchorpeers', async function(req, res) { + logger.debug('==================== UPDATE ANCHOR PEERS =================='); + var channelName = req.params.channelName; + var configUpdatePath = req.body.configUpdatePath; + logger.debug('Channel name : ' + channelName); + logger.debug('configUpdatePath : ' + configUpdatePath); + if (!channelName) { + res.json(getErrorMessage('\'channelName\'')); + return; + } + if (!configUpdatePath) { + res.json(getErrorMessage('\'configUpdatePath\'')); + return; + } + + let message = await updateAnchorPeers.updateAnchorPeers(channelName, configUpdatePath, req.username, req.orgname); + res.send(message); +}); // Install chaincode on target peers app.post('/chaincodes', async function(req, res) { logger.debug('==================== INSTALL CHAINCODE =================='); diff --git a/balance-transfer/app/update-anchor-peers.js b/balance-transfer/app/update-anchor-peers.js new file mode 100644 index 00000000..aa961c87 --- /dev/null +++ b/balance-transfer/app/update-anchor-peers.js @@ -0,0 +1,114 @@ +/** + * Copyright Hitachi America, Ltd. All Rights Reserved. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +'use strict'; +var util = require('util'); +var fs = require('fs'); +var path = require('path'); + +var helper = require('./helper.js'); +var logger = helper.getLogger('update-anchor-peers'); + +var updateAnchorPeers = async function(channelName, configUpdatePath, username, org_name) { + logger.debug('\n====== Updating Anchor Peers on \'' + channelName + '\' ======\n'); + var error_message = null; + try { + // first setup the client for this org + var client = await helper.getClientForOrg(org_name, username); + logger.debug('Successfully got the fabric client for the organization "%s"', org_name); + var channel = client.getChannel(channelName); + if(!channel) { + let message = util.format('Channel %s was not defined in the connection profile', channelName); + logger.error(message); + throw new Error(message); + } + + // read in the envelope for the channel config raw bytes + var envelope = fs.readFileSync(path.join(__dirname, configUpdatePath)); + // extract the channel config bytes from the envelope to be signed + var channelConfig = client.extractChannelConfig(envelope); + + //Acting as a client in the given organization provided with "orgName" param + // sign the channel config bytes as "endorsement", this is required by + // the orderer's channel creation policy + // this will use the admin identity assigned to the client when the connection profile was loaded + let signature = client.signChannelConfig(channelConfig); + + let request = { + config: channelConfig, + signatures: [signature], + name: channelName, + txId: client.newTransactionID(true) // get an admin based transactionID + }; + + var promises = []; + let event_hubs = channel.getChannelEventHubsForOrg(); + logger.debug('found %s eventhubs for this organization %s',event_hubs.length, org_name); + event_hubs.forEach((eh) => { + let anchorUpdateEventPromise = new Promise((resolve, reject) => { + logger.debug('anchorUpdateEventPromise - setting up event'); + let event_timeout = setTimeout(() => { + let message = 'REQUEST_TIMEOUT:' + eh.getPeerAddr(); + logger.error(message); + eh.disconnect(); + }, 60000); + eh.registerBlockEvent((block) => { + logger.info('The config update has been committed on peer %s',eh.getPeerAddr()); + clearTimeout(event_timeout); + resolve(); + }, (err) => { + clearTimeout(event_timeout); + logger.error(err); + reject(err); + }, + // the default for 'unregister' is true for block listeners + // so no real need to set here, however for 'disconnect' + // the default is false as most event hubs are long running + // in this use case we are using it only once + {unregister: true, disconnect: true} + ); + eh.connect(); + }); + promises.push(anchorUpdateEventPromise); + }); + + var sendPromise = client.updateChannel(request); + // put the send to the orderer last so that the events get registered and + // are ready for the orderering and committing + promises.push(sendPromise); + let results = await Promise.all(promises); + logger.debug(util.format('------->>> R E S P O N S E : %j', results)); + let response = results.pop(); // orderer results are last in the results + + if (response && response.status === 'SUCCESS') { + logger.info('Successfully update anchor peers to the channel %s', channelName); + } else { + error_message = util.format('Failed to update anchor peers to the channel %s', channelName); + logger.error(error_message); + } + } catch (error) { + logger.error('Failed to update anchor peers due to error: ' + error.stack ? error.stack : error); + error_message = error.toString(); + } + + if (!error_message) { + let message = util.format( + 'Successfully update anchor peers in organization %s to the channel \'%s\'', + org_name, channelName); + logger.info(message); + let response = { + success: true, + message: message + }; + return response; + } else { + let message = util.format('Failed to update anchor peers. cause:%s',error_message); + logger.error(message); + throw new Error(message); + } +}; + +exports.updateAnchorPeers = updateAnchorPeers; diff --git a/balance-transfer/artifacts/channel/Org1MSPanchors.tx b/balance-transfer/artifacts/channel/Org1MSPanchors.tx new file mode 100644 index 0000000000000000000000000000000000000000..104ee50e05f779149e3447269ac3990a264bd081 GIT binary patch literal 284 zcmd;@$;8Fa#mm8@#F<-}oROH9mzpEg%EZ;g#DydfE)>ee?O0HdlbM`Yl9`_;8yp~{FU8Kq3}P@SadWW;r6#7N78OG{;YFDx5Dpg?n`26DW*$&N3(At3 z%_ua35!L7pMxfa>2(t@07~!T%nE}=2C1>Op1*C!uRTq-wlI9XC0CEiU@_~-gORY%E XEyzjLOU};~=r)&v+C!SFV6FoIk7Y?N literal 0 HcmV?d00001 diff --git a/balance-transfer/artifacts/channel/Org2MSPanchors.tx b/balance-transfer/artifacts/channel/Org2MSPanchors.tx new file mode 100644 index 0000000000000000000000000000000000000000..eaaf1d7f12187c6bbf19d3f405cba5f90dad353a GIT binary patch literal 284 zcmd;@$;8Fa#mm8@#F<-}oROH9mzpEg%EZ;g#DydfE)>ee?O0HdlbM`Yl9`_;2(t@07~!T%nE}=2C1>Op1*C!uRTq-wlI9XC0CEiU@_~-gORY%E XEyzjLOU};~=r)&v+C!SFV6FoIkqt>P literal 0 HcmV?d00001 diff --git a/balance-transfer/testAPIs.sh b/balance-transfer/testAPIs.sh index 8528924c..e48ec039 100755 --- a/balance-transfer/testAPIs.sh +++ b/balance-transfer/testAPIs.sh @@ -112,6 +112,30 @@ curl -s -X POST \ echo echo +echo "POST request Update anchor peers on Org1" +echo +curl -s -X POST \ + http://localhost:4000/channels/mychannel/anchorpeers \ + -H "authorization: Bearer $ORG1_TOKEN" \ + -H "content-type: application/json" \ + -d '{ + "configUpdatePath":"../artifacts/channel/Org1MSPanchors.tx" +}' +echo +echo + +echo "POST request Update anchor peers on Org2" +echo +curl -s -X POST \ + http://localhost:4000/channels/mychannel/anchorpeers \ + -H "authorization: Bearer $ORG2_TOKEN" \ + -H "content-type: application/json" \ + -d '{ + "configUpdatePath":"../artifacts/channel/Org2MSPanchors.tx" +}' +echo +echo + echo "POST Install chaincode on Org1" echo curl -s -X POST \ From 6dc5ce503bdd54d8c48ffead610d19d2993ab3db Mon Sep 17 00:00:00 2001 From: sebastianpaulp Date: Wed, 24 Oct 2018 21:23:24 +0530 Subject: [PATCH 28/35] [FAB-12587] Fix for Query Block by block hash API Block Query by hash Fixed in balance transfer app. Change-Id: Iad5c0af657e7359ee787e1f939a6695d470da1cd Signed-off-by: sebastianpaulp --- balance-transfer/app/query.js | 2 +- balance-transfer/testAPIs.sh | 33 ++++++++++++++++----------------- 2 files changed, 17 insertions(+), 18 deletions(-) diff --git a/balance-transfer/app/query.js b/balance-transfer/app/query.js index 3ff95022..11a5b7a2 100644 --- a/balance-transfer/app/query.js +++ b/balance-transfer/app/query.js @@ -115,7 +115,7 @@ var getBlockByHash = async function(peer, channelName, hash, username, org_name) throw new Error(message); } - let response_payload = await channel.queryBlockByHash(Buffer.from(hash), peer); + let response_payload = await channel.queryBlockByHash(Buffer.from(hash,'hex'), peer); if (response_payload) { logger.debug(response_payload); return response_payload; diff --git a/balance-transfer/testAPIs.sh b/balance-transfer/testAPIs.sh index e48ec039..a8ec82bc 100755 --- a/balance-transfer/testAPIs.sh +++ b/balance-transfer/testAPIs.sh @@ -209,11 +209,13 @@ echo echo "GET query Block by blockNumber" echo -curl -s -X GET \ +BLOCK_INFO=$(curl -s -X GET \ "http://localhost:4000/channels/mychannel/blocks/1?peer=peer0.org1.example.com" \ -H "authorization: Bearer $ORG1_TOKEN" \ - -H "content-type: application/json" -echo + -H "content-type: application/json") +echo $BLOCK_INFO +# Assign previvious block hash to HASH +HASH=$(echo $BLOCK_INFO | jq -r ".header.previous_hash") echo echo "GET query Transaction by TransactionID" @@ -224,20 +226,17 @@ curl -s -X GET http://localhost:4000/channels/mychannel/transactions/$TRX_ID?pee echo echo -############################################################################ -### TODO: What to pass to fetch the Block information -############################################################################ -#echo "GET query Block by Hash" -#echo -#hash=???? -#curl -s -X GET \ -# "http://localhost:4000/channels/mychannel/blocks?hash=$hash&peer=peer1" \ -# -H "authorization: Bearer $ORG1_TOKEN" \ -# -H "cache-control: no-cache" \ -# -H "content-type: application/json" \ -# -H "x-access-token: $ORG1_TOKEN" -#echo -#echo + +echo "GET query Block by Hash - Hash is $HASH" +echo +curl -s -X GET \ + "http://localhost:4000/channels/mychannel/blocks?hash=$HASH&peer=peer0.org1.example.com" \ + -H "authorization: Bearer $ORG1_TOKEN" \ + -H "cache-control: no-cache" \ + -H "content-type: application/json" \ + -H "x-access-token: $ORG1_TOKEN" +echo +echo echo "GET query ChainInfo" echo From 24c5e475393139dd75fb3970c65e1ac3fd0a6feb Mon Sep 17 00:00:00 2001 From: zhaochy Date: Fri, 21 Sep 2018 11:01:36 +0800 Subject: [PATCH 29/35] [FAB-12026] pagination samples for node marbles02 This change synchronizes the node marbles02 sample chaincode with fabric/examples/marbles02 Change-Id: I6c11fee15ae39950fca7344fbf230c42f876274a Signed-off-by: zhaochy --- chaincode/marbles02/node/marbles_chaincode.js | 76 ++++++++++++++++++- 1 file changed, 74 insertions(+), 2 deletions(-) diff --git a/chaincode/marbles02/node/marbles_chaincode.js b/chaincode/marbles02/node/marbles_chaincode.js index 60484df0..4a9a3b7e 100644 --- a/chaincode/marbles02/node/marbles_chaincode.js +++ b/chaincode/marbles02/node/marbles_chaincode.js @@ -18,10 +18,14 @@ // peer chaincode query -C myc1 -n marbles -c '{"Args":["readMarble","marble1"]}' // peer chaincode query -C myc1 -n marbles -c '{"Args":["getMarblesByRange","marble1","marble3"]}' // peer chaincode query -C myc1 -n marbles -c '{"Args":["getHistoryForMarble","marble1"]}' +// peer chaincode query -C myc1 -n marbles -c '{"Args":["getMarblesByRangeWithPagination","marble1","marble3","3",""]}' // Rich Query (Only supported if CouchDB is used as state database): -// peer chaincode query -C myc1 -n marbles -c '{"Args":["queryMarblesByOwner","tom"]}' -// peer chaincode query -C myc1 -n marbles -c '{"Args":["queryMarbles","{\"selector\":{\"owner\":\"tom\"}}"]}' +// peer chaincode query -C myc1 -n marbles -c '{"Args":["queryMarblesByOwner","tom"]}' +// peer chaincode query -C myc1 -n marbles -c '{"Args":["queryMarbles","{\"selector\":{\"owner\":\"tom\"}}"]}' + +// Rich Query with Pagination (Only supported if CouchDB is used as state database): +// peer chaincode query -C myc1 -n marbles -c '{"Args":["queryMarblesWithPagination","{\"selector\":{\"owner\":\"tom\"}}","3",""]}' 'use strict'; const shim = require('fabric-shim'); @@ -404,6 +408,74 @@ let Chaincode = class { return Buffer.from(JSON.stringify(results)); } + + // ====== Pagination ========================================================================= + // Pagination provides a method to retrieve records with a defined pagesize and + // start point (bookmark). An empty string bookmark defines the first "page" of a query + // result. Paginated queries return a bookmark that can be used in + // the next query to retrieve the next page of results. Paginated queries extend + // rich queries and range queries to include a pagesize and bookmark. + // + // Two examples are provided in this example. The first is getMarblesByRangeWithPagination + // which executes a paginated range query. + // The second example is a paginated query for rich ad-hoc queries. + // ========================================================================================= + + // ====== Example: Pagination with Range Query =============================================== + // getMarblesByRangeWithPagination performs a range query based on the start & end key, + // page size and a bookmark. + // + // The number of fetched records will be equal to or lesser than the page size. + // Paginated range queries are only valid for read only transactions. + // =========================================================================================== + async getMarblesByRangeWithPagination(stub, args, thisClass) { + if (args.length < 2) { + throw new Error('Incorrect number of arguments. Expecting 2'); + } + const startKey = args[0]; + const endKey = args[1]; + + const pageSize = parseInt(args[2], 10); + const bookmark = args[3]; + + const { iterator, metadata } = await stub.getStateByRangeWithPagination(startKey, endKey, pageSize, bookmark); + const getAllResults = thisClass['getAllResults']; + const results = await getAllResults(iterator, false); + // use RecordsCount and Bookmark to keep consistency with the go sample + results.ResponseMetadata = { + RecordsCount: metadata.fetched_records_count, + Bookmark: metadata.bookmark, + }; + return Buffer.from(JSON.stringify(results)); + } + + // ========================================================================================= + // getQueryResultForQueryStringWithPagination executes the passed in query string with + // pagination info. Result set is built and returned as a byte array containing the JSON results. + // ========================================================================================= + async queryMarblesWithPagination(stub, args, thisClass) { + + // 0 + // "queryString" + if (args.length < 3) { + return shim.Error("Incorrect number of arguments. Expecting 3") + } + + const queryString = args[0]; + const pageSize = parseInt(args[2], 10); + const bookmark = args[3]; + + const { iterator, metadata } = await stub.GetQueryResultWithPagination(queryString, pageSize, bookmark); + const getAllResults = thisClass['getAllResults']; + const results = await getAllResults(iterator, false); + // use RecordsCount and Bookmark to keep consistency with the go sample + results.ResponseMetadata = { + RecordsCount: metadata.fetched_records_count, + Bookmark: metadata.bookmark, + }; + + return Buffer.from(JSON.stringify(results)); + } }; shim.start(new Chaincode()); From 286861e0e37f11383bf298bb8d6e49703087cf72 Mon Sep 17 00:00:00 2001 From: Yuki Kondo Date: Fri, 12 Oct 2018 18:36:56 +0000 Subject: [PATCH 30/35] [FAB-12371]Fix the abac sample to use new cid package The latest cid package is fabric/core/chaincode/shim/ext/cid. This CR fixes the abac sample to use the new cid package instead of the old one at fabric/core/chaincode/lib/cid. The vendor folder is also updated with the new cid package. Change-Id: Ifc431ee4504cd009f84f9d5de271721597bba6e7 Signed-off-by: Yuki Kondo --- chaincode/abac/go/abac.go | 2 +- .../vendor/github.com/golang/protobuf/LICENSE | 3 - .../github.com/golang/protobuf/proto/Makefile | 43 - .../github.com/golang/protobuf/proto/clone.go | 46 +- .../golang/protobuf/proto/decode.go | 669 +--- .../golang/protobuf/proto/deprecated.go | 38 + .../golang/protobuf/proto/discard.go | 201 +- .../golang/protobuf/proto/encode.go | 1207 +------ .../github.com/golang/protobuf/proto/equal.go | 30 +- .../golang/protobuf/proto/extensions.go | 210 +- .../github.com/golang/protobuf/proto/lib.go | 148 +- .../golang/protobuf/proto/message_set.go | 81 +- .../golang/protobuf/proto/pointer_reflect.go | 645 ++-- .../golang/protobuf/proto/pointer_unsafe.go | 402 +-- .../golang/protobuf/proto/properties.go | 447 +-- .../golang/protobuf/proto/table_marshal.go | 2767 +++++++++++++++++ .../golang/protobuf/proto/table_merge.go | 654 ++++ .../golang/protobuf/proto/table_unmarshal.go | 2051 ++++++++++++ .../github.com/golang/protobuf/proto/text.go | 65 +- .../golang/protobuf/proto/text_parser.go | 83 +- .../chaincode/shim/ext}/attrmgr/attrmgr.go | 50 + .../chaincode/{lib => shim/ext}/cid/README.md | 0 .../chaincode/{lib => shim/ext}/cid/cid.go | 24 +- .../{lib => shim/ext}/cid/interfaces.go | 0 .../fabric/protos/msp/identities.pb.go | 179 ++ .../fabric/protos/msp/identities.proto | 49 + .../fabric/protos/msp/msp_config.go | 41 + .../fabric/protos/msp/msp_config.pb.go | 743 +++++ .../fabric/protos/msp/msp_config.proto | 208 ++ .../fabric/protos/msp/msp_principal.go | 43 + .../fabric/protos/msp/msp_principal.pb.go | 437 +++ .../fabric/protos/msp/msp_principal.proto | 153 + .../go/vendor/github.com/pkg/errors/errors.go | 43 +- chaincode/abac/go/vendor/vendor.json | 34 +- fabric-ca/README.md | 4 +- 35 files changed, 8645 insertions(+), 3155 deletions(-) delete mode 100644 chaincode/abac/go/vendor/github.com/golang/protobuf/proto/Makefile create mode 100644 chaincode/abac/go/vendor/github.com/golang/protobuf/proto/deprecated.go create mode 100644 chaincode/abac/go/vendor/github.com/golang/protobuf/proto/table_marshal.go create mode 100644 chaincode/abac/go/vendor/github.com/golang/protobuf/proto/table_merge.go create mode 100644 chaincode/abac/go/vendor/github.com/golang/protobuf/proto/table_unmarshal.go rename chaincode/abac/go/vendor/github.com/hyperledger/fabric/{common => core/chaincode/shim/ext}/attrmgr/attrmgr.go (81%) rename chaincode/abac/go/vendor/github.com/hyperledger/fabric/core/chaincode/{lib => shim/ext}/cid/README.md (100%) rename chaincode/abac/go/vendor/github.com/hyperledger/fabric/core/chaincode/{lib => shim/ext}/cid/cid.go (90%) rename chaincode/abac/go/vendor/github.com/hyperledger/fabric/core/chaincode/{lib => shim/ext}/cid/interfaces.go (100%) create mode 100644 chaincode/abac/go/vendor/github.com/hyperledger/fabric/protos/msp/identities.pb.go create mode 100644 chaincode/abac/go/vendor/github.com/hyperledger/fabric/protos/msp/identities.proto create mode 100644 chaincode/abac/go/vendor/github.com/hyperledger/fabric/protos/msp/msp_config.go create mode 100644 chaincode/abac/go/vendor/github.com/hyperledger/fabric/protos/msp/msp_config.pb.go create mode 100644 chaincode/abac/go/vendor/github.com/hyperledger/fabric/protos/msp/msp_config.proto create mode 100644 chaincode/abac/go/vendor/github.com/hyperledger/fabric/protos/msp/msp_principal.go create mode 100644 chaincode/abac/go/vendor/github.com/hyperledger/fabric/protos/msp/msp_principal.pb.go create mode 100644 chaincode/abac/go/vendor/github.com/hyperledger/fabric/protos/msp/msp_principal.proto diff --git a/chaincode/abac/go/abac.go b/chaincode/abac/go/abac.go index 78f8bfb7..b54367bf 100644 --- a/chaincode/abac/go/abac.go +++ b/chaincode/abac/go/abac.go @@ -20,7 +20,7 @@ import ( "fmt" "strconv" - "github.com/hyperledger/fabric/core/chaincode/lib/cid" + "github.com/hyperledger/fabric/core/chaincode/shim/ext/cid" "github.com/hyperledger/fabric/core/chaincode/shim" pb "github.com/hyperledger/fabric/protos/peer" ) diff --git a/chaincode/abac/go/vendor/github.com/golang/protobuf/LICENSE b/chaincode/abac/go/vendor/github.com/golang/protobuf/LICENSE index 1b1b1921..0f646931 100644 --- a/chaincode/abac/go/vendor/github.com/golang/protobuf/LICENSE +++ b/chaincode/abac/go/vendor/github.com/golang/protobuf/LICENSE @@ -1,7 +1,4 @@ -Go support for Protocol Buffers - Google's data interchange format - Copyright 2010 The Go Authors. All rights reserved. -https://github.com/golang/protobuf Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are diff --git a/chaincode/abac/go/vendor/github.com/golang/protobuf/proto/Makefile b/chaincode/abac/go/vendor/github.com/golang/protobuf/proto/Makefile deleted file mode 100644 index e2e0651a..00000000 --- a/chaincode/abac/go/vendor/github.com/golang/protobuf/proto/Makefile +++ /dev/null @@ -1,43 +0,0 @@ -# Go support for Protocol Buffers - Google's data interchange format -# -# Copyright 2010 The Go Authors. All rights reserved. -# https://github.com/golang/protobuf -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: -# -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above -# copyright notice, this list of conditions and the following disclaimer -# in the documentation and/or other materials provided with the -# distribution. -# * Neither the name of Google Inc. nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -install: - go install - -test: install generate-test-pbs - go test - - -generate-test-pbs: - make install - make -C testdata - protoc --go_out=Mtestdata/test.proto=github.com/golang/protobuf/proto/testdata,Mgoogle/protobuf/any.proto=github.com/golang/protobuf/ptypes/any:. proto3_proto/proto3.proto - make diff --git a/chaincode/abac/go/vendor/github.com/golang/protobuf/proto/clone.go b/chaincode/abac/go/vendor/github.com/golang/protobuf/proto/clone.go index e392575b..3cd3249f 100644 --- a/chaincode/abac/go/vendor/github.com/golang/protobuf/proto/clone.go +++ b/chaincode/abac/go/vendor/github.com/golang/protobuf/proto/clone.go @@ -35,22 +35,39 @@ package proto import ( + "fmt" "log" "reflect" "strings" ) // Clone returns a deep copy of a protocol buffer. -func Clone(pb Message) Message { - in := reflect.ValueOf(pb) +func Clone(src Message) Message { + in := reflect.ValueOf(src) if in.IsNil() { - return pb + return src } - out := reflect.New(in.Type().Elem()) - // out is empty so a merge is a deep copy. - mergeStruct(out.Elem(), in.Elem()) - return out.Interface().(Message) + dst := out.Interface().(Message) + Merge(dst, src) + return dst +} + +// Merger is the interface representing objects that can merge messages of the same type. +type Merger interface { + // Merge merges src into this message. + // Required and optional fields that are set in src will be set to that value in dst. + // Elements of repeated fields will be appended. + // + // Merge may panic if called with a different argument type than the receiver. + Merge(src Message) +} + +// generatedMerger is the custom merge method that generated protos will have. +// We must add this method since a generate Merge method will conflict with +// many existing protos that have a Merge data field already defined. +type generatedMerger interface { + XXX_Merge(src Message) } // Merge merges src into dst. @@ -58,17 +75,24 @@ func Clone(pb Message) Message { // Elements of repeated fields will be appended. // Merge panics if src and dst are not the same type, or if dst is nil. func Merge(dst, src Message) { + if m, ok := dst.(Merger); ok { + m.Merge(src) + return + } + in := reflect.ValueOf(src) out := reflect.ValueOf(dst) if out.IsNil() { panic("proto: nil destination") } if in.Type() != out.Type() { - // Explicit test prior to mergeStruct so that mistyped nils will fail - panic("proto: type mismatch") + panic(fmt.Sprintf("proto.Merge(%T, %T) type mismatch", dst, src)) } if in.IsNil() { - // Merging nil into non-nil is a quiet no-op + return // Merge from nil src is a noop + } + if m, ok := dst.(generatedMerger); ok { + m.XXX_Merge(src) return } mergeStruct(out.Elem(), in.Elem()) @@ -84,7 +108,7 @@ func mergeStruct(out, in reflect.Value) { mergeAny(out.Field(i), in.Field(i), false, sprop.Prop[i]) } - if emIn, ok := extendable(in.Addr().Interface()); ok { + if emIn, err := extendable(in.Addr().Interface()); err == nil { emOut, _ := extendable(out.Addr().Interface()) mIn, muIn := emIn.extensionsRead() if mIn != nil { diff --git a/chaincode/abac/go/vendor/github.com/golang/protobuf/proto/decode.go b/chaincode/abac/go/vendor/github.com/golang/protobuf/proto/decode.go index aa207298..63b0f08b 100644 --- a/chaincode/abac/go/vendor/github.com/golang/protobuf/proto/decode.go +++ b/chaincode/abac/go/vendor/github.com/golang/protobuf/proto/decode.go @@ -39,8 +39,6 @@ import ( "errors" "fmt" "io" - "os" - "reflect" ) // errOverflow is returned when an integer is too large to be represented. @@ -50,10 +48,6 @@ var errOverflow = errors.New("proto: integer overflow") // wire type is encountered. It does not get returned to user code. var ErrInternalBadWireType = errors.New("proto: internal error: bad wiretype for oneof") -// The fundamental decoders that interpret bytes on the wire. -// Those that take integer types all return uint64 and are -// therefore of type valueDecoder. - // DecodeVarint reads a varint-encoded integer from the slice. // It returns the integer and the number of bytes consumed, or // zero if there is not enough. @@ -192,7 +186,6 @@ func (p *Buffer) DecodeVarint() (x uint64, err error) { if b&0x80 == 0 { goto done } - // x -= 0x80 << 63 // Always zero. return 0, errOverflow @@ -267,9 +260,6 @@ func (p *Buffer) DecodeZigzag32() (x uint64, err error) { return } -// These are not ValueDecoders: they produce an array of bytes or a string. -// bytes, embedded messages - // DecodeRawBytes reads a count-delimited byte buffer from the Buffer. // This is the format used for the bytes protocol buffer // type and for embedded messages. @@ -311,81 +301,29 @@ func (p *Buffer) DecodeStringBytes() (s string, err error) { return string(buf), nil } -// Skip the next item in the buffer. Its wire type is decoded and presented as an argument. -// If the protocol buffer has extensions, and the field matches, add it as an extension. -// Otherwise, if the XXX_unrecognized field exists, append the skipped data there. -func (o *Buffer) skipAndSave(t reflect.Type, tag, wire int, base structPointer, unrecField field) error { - oi := o.index - - err := o.skip(t, tag, wire) - if err != nil { - return err - } - - if !unrecField.IsValid() { - return nil - } - - ptr := structPointer_Bytes(base, unrecField) - - // Add the skipped field to struct field - obuf := o.buf - - o.buf = *ptr - o.EncodeVarint(uint64(tag<<3 | wire)) - *ptr = append(o.buf, obuf[oi:o.index]...) - - o.buf = obuf - - return nil -} - -// Skip the next item in the buffer. Its wire type is decoded and presented as an argument. -func (o *Buffer) skip(t reflect.Type, tag, wire int) error { - - var u uint64 - var err error - - switch wire { - case WireVarint: - _, err = o.DecodeVarint() - case WireFixed64: - _, err = o.DecodeFixed64() - case WireBytes: - _, err = o.DecodeRawBytes(false) - case WireFixed32: - _, err = o.DecodeFixed32() - case WireStartGroup: - for { - u, err = o.DecodeVarint() - if err != nil { - break - } - fwire := int(u & 0x7) - if fwire == WireEndGroup { - break - } - ftag := int(u >> 3) - err = o.skip(t, ftag, fwire) - if err != nil { - break - } - } - default: - err = fmt.Errorf("proto: can't skip unknown wire type %d for %s", wire, t) - } - return err -} - // Unmarshaler is the interface representing objects that can -// unmarshal themselves. The method should reset the receiver before -// decoding starts. The argument points to data that may be +// unmarshal themselves. The argument points to data that may be // overwritten, so implementations should not keep references to the // buffer. +// Unmarshal implementations should not clear the receiver. +// Any unmarshaled data should be merged into the receiver. +// Callers of Unmarshal that do not want to retain existing data +// should Reset the receiver before calling Unmarshal. type Unmarshaler interface { Unmarshal([]byte) error } +// newUnmarshaler is the interface representing objects that can +// unmarshal themselves. The semantics are identical to Unmarshaler. +// +// This exists to support protoc-gen-go generated messages. +// The proto package will stop type-asserting to this interface in the future. +// +// DO NOT DEPEND ON THIS. +type newUnmarshaler interface { + XXX_Unmarshal([]byte) error +} + // Unmarshal parses the protocol buffer representation in buf and places the // decoded result in pb. If the struct underlying pb does not match // the data in buf, the results can be unpredictable. @@ -395,7 +333,13 @@ type Unmarshaler interface { // to preserve and append to existing data. func Unmarshal(buf []byte, pb Message) error { pb.Reset() - return UnmarshalMerge(buf, pb) + if u, ok := pb.(newUnmarshaler); ok { + return u.XXX_Unmarshal(buf) + } + if u, ok := pb.(Unmarshaler); ok { + return u.Unmarshal(buf) + } + return NewBuffer(buf).Unmarshal(pb) } // UnmarshalMerge parses the protocol buffer representation in buf and @@ -405,8 +349,16 @@ func Unmarshal(buf []byte, pb Message) error { // UnmarshalMerge merges into existing data in pb. // Most code should use Unmarshal instead. func UnmarshalMerge(buf []byte, pb Message) error { - // If the object can unmarshal itself, let it. + if u, ok := pb.(newUnmarshaler); ok { + return u.XXX_Unmarshal(buf) + } if u, ok := pb.(Unmarshaler); ok { + // NOTE: The history of proto have unfortunately been inconsistent + // whether Unmarshaler should or should not implicitly clear itself. + // Some implementations do, most do not. + // Thus, calling this here may or may not do what people want. + // + // See https://github.com/golang/protobuf/issues/424 return u.Unmarshal(buf) } return NewBuffer(buf).Unmarshal(pb) @@ -422,12 +374,17 @@ func (p *Buffer) DecodeMessage(pb Message) error { } // DecodeGroup reads a tag-delimited group from the Buffer. +// StartGroup tag is already consumed. This function consumes +// EndGroup tag. func (p *Buffer) DecodeGroup(pb Message) error { - typ, base, err := getbase(pb) - if err != nil { - return err + b := p.buf[p.index:] + x, y := findEndGroup(b) + if x < 0 { + return io.ErrUnexpectedEOF } - return p.unmarshalType(typ.Elem(), GetProperties(typ.Elem()), true, base) + err := Unmarshal(b[:x], pb) + p.index += y + return err } // Unmarshal parses the protocol buffer representation in the @@ -438,533 +395,33 @@ func (p *Buffer) DecodeGroup(pb Message) error { // Unlike proto.Unmarshal, this does not reset pb before starting to unmarshal. func (p *Buffer) Unmarshal(pb Message) error { // If the object can unmarshal itself, let it. + if u, ok := pb.(newUnmarshaler); ok { + err := u.XXX_Unmarshal(p.buf[p.index:]) + p.index = len(p.buf) + return err + } if u, ok := pb.(Unmarshaler); ok { + // NOTE: The history of proto have unfortunately been inconsistent + // whether Unmarshaler should or should not implicitly clear itself. + // Some implementations do, most do not. + // Thus, calling this here may or may not do what people want. + // + // See https://github.com/golang/protobuf/issues/424 err := u.Unmarshal(p.buf[p.index:]) p.index = len(p.buf) return err } - typ, base, err := getbase(pb) - if err != nil { - return err - } - - err = p.unmarshalType(typ.Elem(), GetProperties(typ.Elem()), false, base) - - if collectStats { - stats.Decode++ - } - - return err -} - -// unmarshalType does the work of unmarshaling a structure. -func (o *Buffer) unmarshalType(st reflect.Type, prop *StructProperties, is_group bool, base structPointer) error { - var state errorState - required, reqFields := prop.reqCount, uint64(0) - - var err error - for err == nil && o.index < len(o.buf) { - oi := o.index - var u uint64 - u, err = o.DecodeVarint() - if err != nil { - break - } - wire := int(u & 0x7) - if wire == WireEndGroup { - if is_group { - if required > 0 { - // Not enough information to determine the exact field. - // (See below.) - return &RequiredNotSetError{"{Unknown}"} - } - return nil // input is satisfied - } - return fmt.Errorf("proto: %s: wiretype end group for non-group", st) - } - tag := int(u >> 3) - if tag <= 0 { - return fmt.Errorf("proto: %s: illegal tag %d (wire type %d)", st, tag, wire) - } - fieldnum, ok := prop.decoderTags.get(tag) - if !ok { - // Maybe it's an extension? - if prop.extendable { - if e, _ := extendable(structPointer_Interface(base, st)); isExtensionField(e, int32(tag)) { - if err = o.skip(st, tag, wire); err == nil { - extmap := e.extensionsWrite() - ext := extmap[int32(tag)] // may be missing - ext.enc = append(ext.enc, o.buf[oi:o.index]...) - extmap[int32(tag)] = ext - } - continue - } - } - // Maybe it's a oneof? - if prop.oneofUnmarshaler != nil { - m := structPointer_Interface(base, st).(Message) - // First return value indicates whether tag is a oneof field. - ok, err = prop.oneofUnmarshaler(m, tag, wire, o) - if err == ErrInternalBadWireType { - // Map the error to something more descriptive. - // Do the formatting here to save generated code space. - err = fmt.Errorf("bad wiretype for oneof field in %T", m) - } - if ok { - continue - } - } - err = o.skipAndSave(st, tag, wire, base, prop.unrecField) - continue - } - p := prop.Prop[fieldnum] - - if p.dec == nil { - fmt.Fprintf(os.Stderr, "proto: no protobuf decoder for %s.%s\n", st, st.Field(fieldnum).Name) - continue - } - dec := p.dec - if wire != WireStartGroup && wire != p.WireType { - if wire == WireBytes && p.packedDec != nil { - // a packable field - dec = p.packedDec - } else { - err = fmt.Errorf("proto: bad wiretype for field %s.%s: got wiretype %d, want %d", st, st.Field(fieldnum).Name, wire, p.WireType) - continue - } - } - decErr := dec(o, p, base) - if decErr != nil && !state.shouldContinue(decErr, p) { - err = decErr - } - if err == nil && p.Required { - // Successfully decoded a required field. - if tag <= 64 { - // use bitmap for fields 1-64 to catch field reuse. - var mask uint64 = 1 << uint64(tag-1) - if reqFields&mask == 0 { - // new required field - reqFields |= mask - required-- - } - } else { - // This is imprecise. It can be fooled by a required field - // with a tag > 64 that is encoded twice; that's very rare. - // A fully correct implementation would require allocating - // a data structure, which we would like to avoid. - required-- - } - } - } - if err == nil { - if is_group { - return io.ErrUnexpectedEOF - } - if state.err != nil { - return state.err - } - if required > 0 { - // Not enough information to determine the exact field. If we use extra - // CPU, we could determine the field only if the missing required field - // has a tag <= 64 and we check reqFields. - return &RequiredNotSetError{"{Unknown}"} - } - } - return err -} - -// Individual type decoders -// For each, -// u is the decoded value, -// v is a pointer to the field (pointer) in the struct - -// Sizes of the pools to allocate inside the Buffer. -// The goal is modest amortization and allocation -// on at least 16-byte boundaries. -const ( - boolPoolSize = 16 - uint32PoolSize = 8 - uint64PoolSize = 4 -) - -// Decode a bool. -func (o *Buffer) dec_bool(p *Properties, base structPointer) error { - u, err := p.valDec(o) - if err != nil { - return err - } - if len(o.bools) == 0 { - o.bools = make([]bool, boolPoolSize) - } - o.bools[0] = u != 0 - *structPointer_Bool(base, p.field) = &o.bools[0] - o.bools = o.bools[1:] - return nil -} - -func (o *Buffer) dec_proto3_bool(p *Properties, base structPointer) error { - u, err := p.valDec(o) - if err != nil { - return err - } - *structPointer_BoolVal(base, p.field) = u != 0 - return nil -} - -// Decode an int32. -func (o *Buffer) dec_int32(p *Properties, base structPointer) error { - u, err := p.valDec(o) - if err != nil { - return err - } - word32_Set(structPointer_Word32(base, p.field), o, uint32(u)) - return nil -} - -func (o *Buffer) dec_proto3_int32(p *Properties, base structPointer) error { - u, err := p.valDec(o) - if err != nil { - return err - } - word32Val_Set(structPointer_Word32Val(base, p.field), uint32(u)) - return nil -} - -// Decode an int64. -func (o *Buffer) dec_int64(p *Properties, base structPointer) error { - u, err := p.valDec(o) - if err != nil { - return err - } - word64_Set(structPointer_Word64(base, p.field), o, u) - return nil -} - -func (o *Buffer) dec_proto3_int64(p *Properties, base structPointer) error { - u, err := p.valDec(o) - if err != nil { - return err - } - word64Val_Set(structPointer_Word64Val(base, p.field), o, u) - return nil -} - -// Decode a string. -func (o *Buffer) dec_string(p *Properties, base structPointer) error { - s, err := o.DecodeStringBytes() - if err != nil { - return err - } - *structPointer_String(base, p.field) = &s - return nil -} - -func (o *Buffer) dec_proto3_string(p *Properties, base structPointer) error { - s, err := o.DecodeStringBytes() - if err != nil { - return err - } - *structPointer_StringVal(base, p.field) = s - return nil -} - -// Decode a slice of bytes ([]byte). -func (o *Buffer) dec_slice_byte(p *Properties, base structPointer) error { - b, err := o.DecodeRawBytes(true) - if err != nil { - return err - } - *structPointer_Bytes(base, p.field) = b - return nil -} - -// Decode a slice of bools ([]bool). -func (o *Buffer) dec_slice_bool(p *Properties, base structPointer) error { - u, err := p.valDec(o) - if err != nil { - return err - } - v := structPointer_BoolSlice(base, p.field) - *v = append(*v, u != 0) - return nil -} - -// Decode a slice of bools ([]bool) in packed format. -func (o *Buffer) dec_slice_packed_bool(p *Properties, base structPointer) error { - v := structPointer_BoolSlice(base, p.field) - - nn, err := o.DecodeVarint() - if err != nil { - return err - } - nb := int(nn) // number of bytes of encoded bools - fin := o.index + nb - if fin < o.index { - return errOverflow - } - - y := *v - for o.index < fin { - u, err := p.valDec(o) - if err != nil { - return err - } - y = append(y, u != 0) - } - - *v = y - return nil -} - -// Decode a slice of int32s ([]int32). -func (o *Buffer) dec_slice_int32(p *Properties, base structPointer) error { - u, err := p.valDec(o) - if err != nil { - return err - } - structPointer_Word32Slice(base, p.field).Append(uint32(u)) - return nil -} - -// Decode a slice of int32s ([]int32) in packed format. -func (o *Buffer) dec_slice_packed_int32(p *Properties, base structPointer) error { - v := structPointer_Word32Slice(base, p.field) - - nn, err := o.DecodeVarint() - if err != nil { - return err - } - nb := int(nn) // number of bytes of encoded int32s - - fin := o.index + nb - if fin < o.index { - return errOverflow - } - for o.index < fin { - u, err := p.valDec(o) - if err != nil { - return err - } - v.Append(uint32(u)) - } - return nil -} - -// Decode a slice of int64s ([]int64). -func (o *Buffer) dec_slice_int64(p *Properties, base structPointer) error { - u, err := p.valDec(o) - if err != nil { - return err - } - - structPointer_Word64Slice(base, p.field).Append(u) - return nil -} - -// Decode a slice of int64s ([]int64) in packed format. -func (o *Buffer) dec_slice_packed_int64(p *Properties, base structPointer) error { - v := structPointer_Word64Slice(base, p.field) - - nn, err := o.DecodeVarint() - if err != nil { - return err - } - nb := int(nn) // number of bytes of encoded int64s - - fin := o.index + nb - if fin < o.index { - return errOverflow - } - for o.index < fin { - u, err := p.valDec(o) - if err != nil { - return err - } - v.Append(u) - } - return nil -} - -// Decode a slice of strings ([]string). -func (o *Buffer) dec_slice_string(p *Properties, base structPointer) error { - s, err := o.DecodeStringBytes() - if err != nil { - return err - } - v := structPointer_StringSlice(base, p.field) - *v = append(*v, s) - return nil -} - -// Decode a slice of slice of bytes ([][]byte). -func (o *Buffer) dec_slice_slice_byte(p *Properties, base structPointer) error { - b, err := o.DecodeRawBytes(true) - if err != nil { - return err - } - v := structPointer_BytesSlice(base, p.field) - *v = append(*v, b) - return nil -} - -// Decode a map field. -func (o *Buffer) dec_new_map(p *Properties, base structPointer) error { - raw, err := o.DecodeRawBytes(false) - if err != nil { - return err - } - oi := o.index // index at the end of this map entry - o.index -= len(raw) // move buffer back to start of map entry - - mptr := structPointer_NewAt(base, p.field, p.mtype) // *map[K]V - if mptr.Elem().IsNil() { - mptr.Elem().Set(reflect.MakeMap(mptr.Type().Elem())) - } - v := mptr.Elem() // map[K]V - - // Prepare addressable doubly-indirect placeholders for the key and value types. - // See enc_new_map for why. - keyptr := reflect.New(reflect.PtrTo(p.mtype.Key())).Elem() // addressable *K - keybase := toStructPointer(keyptr.Addr()) // **K - - var valbase structPointer - var valptr reflect.Value - switch p.mtype.Elem().Kind() { - case reflect.Slice: - // []byte - var dummy []byte - valptr = reflect.ValueOf(&dummy) // *[]byte - valbase = toStructPointer(valptr) // *[]byte - case reflect.Ptr: - // message; valptr is **Msg; need to allocate the intermediate pointer - valptr = reflect.New(reflect.PtrTo(p.mtype.Elem())).Elem() // addressable *V - valptr.Set(reflect.New(valptr.Type().Elem())) - valbase = toStructPointer(valptr) - default: - // everything else - valptr = reflect.New(reflect.PtrTo(p.mtype.Elem())).Elem() // addressable *V - valbase = toStructPointer(valptr.Addr()) // **V - } - - // Decode. - // This parses a restricted wire format, namely the encoding of a message - // with two fields. See enc_new_map for the format. - for o.index < oi { - // tagcode for key and value properties are always a single byte - // because they have tags 1 and 2. - tagcode := o.buf[o.index] - o.index++ - switch tagcode { - case p.mkeyprop.tagcode[0]: - if err := p.mkeyprop.dec(o, p.mkeyprop, keybase); err != nil { - return err - } - case p.mvalprop.tagcode[0]: - if err := p.mvalprop.dec(o, p.mvalprop, valbase); err != nil { - return err - } - default: - // TODO: Should we silently skip this instead? - return fmt.Errorf("proto: bad map data tag %d", raw[0]) - } - } - keyelem, valelem := keyptr.Elem(), valptr.Elem() - if !keyelem.IsValid() { - keyelem = reflect.Zero(p.mtype.Key()) - } - if !valelem.IsValid() { - valelem = reflect.Zero(p.mtype.Elem()) - } - - v.SetMapIndex(keyelem, valelem) - return nil -} - -// Decode a group. -func (o *Buffer) dec_struct_group(p *Properties, base structPointer) error { - bas := structPointer_GetStructPointer(base, p.field) - if structPointer_IsNil(bas) { - // allocate new nested message - bas = toStructPointer(reflect.New(p.stype)) - structPointer_SetStructPointer(base, p.field, bas) - } - return o.unmarshalType(p.stype, p.sprop, true, bas) -} - -// Decode an embedded message. -func (o *Buffer) dec_struct_message(p *Properties, base structPointer) (err error) { - raw, e := o.DecodeRawBytes(false) - if e != nil { - return e - } - - bas := structPointer_GetStructPointer(base, p.field) - if structPointer_IsNil(bas) { - // allocate new nested message - bas = toStructPointer(reflect.New(p.stype)) - structPointer_SetStructPointer(base, p.field, bas) - } - - // If the object can unmarshal itself, let it. - if p.isUnmarshaler { - iv := structPointer_Interface(bas, p.stype) - return iv.(Unmarshaler).Unmarshal(raw) - } - - obuf := o.buf - oi := o.index - o.buf = raw - o.index = 0 - - err = o.unmarshalType(p.stype, p.sprop, false, bas) - o.buf = obuf - o.index = oi - - return err -} - -// Decode a slice of embedded messages. -func (o *Buffer) dec_slice_struct_message(p *Properties, base structPointer) error { - return o.dec_slice_struct(p, false, base) -} - -// Decode a slice of embedded groups. -func (o *Buffer) dec_slice_struct_group(p *Properties, base structPointer) error { - return o.dec_slice_struct(p, true, base) -} - -// Decode a slice of structs ([]*struct). -func (o *Buffer) dec_slice_struct(p *Properties, is_group bool, base structPointer) error { - v := reflect.New(p.stype) - bas := toStructPointer(v) - structPointer_StructPointerSlice(base, p.field).Append(bas) - - if is_group { - err := o.unmarshalType(p.stype, p.sprop, is_group, bas) - return err - } - - raw, err := o.DecodeRawBytes(false) - if err != nil { - return err - } - - // If the object can unmarshal itself, let it. - if p.isUnmarshaler { - iv := v.Interface() - return iv.(Unmarshaler).Unmarshal(raw) - } - - obuf := o.buf - oi := o.index - o.buf = raw - o.index = 0 - - err = o.unmarshalType(p.stype, p.sprop, is_group, bas) - - o.buf = obuf - o.index = oi - + // Slow workaround for messages that aren't Unmarshalers. + // This includes some hand-coded .pb.go files and + // bootstrap protos. + // TODO: fix all of those and then add Unmarshal to + // the Message interface. Then: + // The cast above and code below can be deleted. + // The old unmarshaler can be deleted. + // Clients can call Unmarshal directly (can already do that, actually). + var info InternalMessageInfo + err := info.Unmarshal(pb, p.buf[p.index:]) + p.index = len(p.buf) return err } diff --git a/chaincode/abac/go/vendor/github.com/golang/protobuf/proto/deprecated.go b/chaincode/abac/go/vendor/github.com/golang/protobuf/proto/deprecated.go new file mode 100644 index 00000000..69de0ea0 --- /dev/null +++ b/chaincode/abac/go/vendor/github.com/golang/protobuf/proto/deprecated.go @@ -0,0 +1,38 @@ +// Go support for Protocol Buffers - Google's data interchange format +// +// Copyright 2018 The Go Authors. All rights reserved. +// https://github.com/golang/protobuf +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +package proto + +// Deprecated: do not use. +type Stats struct{ Emalloc, Dmalloc, Encode, Decode, Chit, Cmiss, Size uint64 } + +// Deprecated: do not use. +func GetStats() Stats { return Stats{} } diff --git a/chaincode/abac/go/vendor/github.com/golang/protobuf/proto/discard.go b/chaincode/abac/go/vendor/github.com/golang/protobuf/proto/discard.go index bd0e3bb4..dea2617c 100644 --- a/chaincode/abac/go/vendor/github.com/golang/protobuf/proto/discard.go +++ b/chaincode/abac/go/vendor/github.com/golang/protobuf/proto/discard.go @@ -35,8 +35,14 @@ import ( "fmt" "reflect" "strings" + "sync" + "sync/atomic" ) +type generatedDiscarder interface { + XXX_DiscardUnknown() +} + // DiscardUnknown recursively discards all unknown fields from this message // and all embedded messages. // @@ -49,9 +55,202 @@ import ( // For proto2 messages, the unknown fields of message extensions are only // discarded from messages that have been accessed via GetExtension. func DiscardUnknown(m Message) { + if m, ok := m.(generatedDiscarder); ok { + m.XXX_DiscardUnknown() + return + } + // TODO: Dynamically populate a InternalMessageInfo for legacy messages, + // but the master branch has no implementation for InternalMessageInfo, + // so it would be more work to replicate that approach. discardLegacy(m) } +// DiscardUnknown recursively discards all unknown fields. +func (a *InternalMessageInfo) DiscardUnknown(m Message) { + di := atomicLoadDiscardInfo(&a.discard) + if di == nil { + di = getDiscardInfo(reflect.TypeOf(m).Elem()) + atomicStoreDiscardInfo(&a.discard, di) + } + di.discard(toPointer(&m)) +} + +type discardInfo struct { + typ reflect.Type + + initialized int32 // 0: only typ is valid, 1: everything is valid + lock sync.Mutex + + fields []discardFieldInfo + unrecognized field +} + +type discardFieldInfo struct { + field field // Offset of field, guaranteed to be valid + discard func(src pointer) +} + +var ( + discardInfoMap = map[reflect.Type]*discardInfo{} + discardInfoLock sync.Mutex +) + +func getDiscardInfo(t reflect.Type) *discardInfo { + discardInfoLock.Lock() + defer discardInfoLock.Unlock() + di := discardInfoMap[t] + if di == nil { + di = &discardInfo{typ: t} + discardInfoMap[t] = di + } + return di +} + +func (di *discardInfo) discard(src pointer) { + if src.isNil() { + return // Nothing to do. + } + + if atomic.LoadInt32(&di.initialized) == 0 { + di.computeDiscardInfo() + } + + for _, fi := range di.fields { + sfp := src.offset(fi.field) + fi.discard(sfp) + } + + // For proto2 messages, only discard unknown fields in message extensions + // that have been accessed via GetExtension. + if em, err := extendable(src.asPointerTo(di.typ).Interface()); err == nil { + // Ignore lock since DiscardUnknown is not concurrency safe. + emm, _ := em.extensionsRead() + for _, mx := range emm { + if m, ok := mx.value.(Message); ok { + DiscardUnknown(m) + } + } + } + + if di.unrecognized.IsValid() { + *src.offset(di.unrecognized).toBytes() = nil + } +} + +func (di *discardInfo) computeDiscardInfo() { + di.lock.Lock() + defer di.lock.Unlock() + if di.initialized != 0 { + return + } + t := di.typ + n := t.NumField() + + for i := 0; i < n; i++ { + f := t.Field(i) + if strings.HasPrefix(f.Name, "XXX_") { + continue + } + + dfi := discardFieldInfo{field: toField(&f)} + tf := f.Type + + // Unwrap tf to get its most basic type. + var isPointer, isSlice bool + if tf.Kind() == reflect.Slice && tf.Elem().Kind() != reflect.Uint8 { + isSlice = true + tf = tf.Elem() + } + if tf.Kind() == reflect.Ptr { + isPointer = true + tf = tf.Elem() + } + if isPointer && isSlice && tf.Kind() != reflect.Struct { + panic(fmt.Sprintf("%v.%s cannot be a slice of pointers to primitive types", t, f.Name)) + } + + switch tf.Kind() { + case reflect.Struct: + switch { + case !isPointer: + panic(fmt.Sprintf("%v.%s cannot be a direct struct value", t, f.Name)) + case isSlice: // E.g., []*pb.T + di := getDiscardInfo(tf) + dfi.discard = func(src pointer) { + sps := src.getPointerSlice() + for _, sp := range sps { + if !sp.isNil() { + di.discard(sp) + } + } + } + default: // E.g., *pb.T + di := getDiscardInfo(tf) + dfi.discard = func(src pointer) { + sp := src.getPointer() + if !sp.isNil() { + di.discard(sp) + } + } + } + case reflect.Map: + switch { + case isPointer || isSlice: + panic(fmt.Sprintf("%v.%s cannot be a pointer to a map or a slice of map values", t, f.Name)) + default: // E.g., map[K]V + if tf.Elem().Kind() == reflect.Ptr { // Proto struct (e.g., *T) + dfi.discard = func(src pointer) { + sm := src.asPointerTo(tf).Elem() + if sm.Len() == 0 { + return + } + for _, key := range sm.MapKeys() { + val := sm.MapIndex(key) + DiscardUnknown(val.Interface().(Message)) + } + } + } else { + dfi.discard = func(pointer) {} // Noop + } + } + case reflect.Interface: + // Must be oneof field. + switch { + case isPointer || isSlice: + panic(fmt.Sprintf("%v.%s cannot be a pointer to a interface or a slice of interface values", t, f.Name)) + default: // E.g., interface{} + // TODO: Make this faster? + dfi.discard = func(src pointer) { + su := src.asPointerTo(tf).Elem() + if !su.IsNil() { + sv := su.Elem().Elem().Field(0) + if sv.Kind() == reflect.Ptr && sv.IsNil() { + return + } + switch sv.Type().Kind() { + case reflect.Ptr: // Proto struct (e.g., *T) + DiscardUnknown(sv.Interface().(Message)) + } + } + } + } + default: + continue + } + di.fields = append(di.fields, dfi) + } + + di.unrecognized = invalidField + if f, ok := t.FieldByName("XXX_unrecognized"); ok { + if f.Type != reflect.TypeOf([]byte{}) { + panic("expected XXX_unrecognized to be of type []byte") + } + di.unrecognized = toField(&f) + } + + atomic.StoreInt32(&di.initialized, 1) +} + func discardLegacy(m Message) { v := reflect.ValueOf(m) if v.Kind() != reflect.Ptr || v.IsNil() { @@ -139,7 +338,7 @@ func discardLegacy(m Message) { // For proto2 messages, only discard unknown fields in message extensions // that have been accessed via GetExtension. - if em, ok := extendable(m); ok { + if em, err := extendable(m); err == nil { // Ignore lock since discardLegacy is not concurrency safe. emm, _ := em.extensionsRead() for _, mx := range emm { diff --git a/chaincode/abac/go/vendor/github.com/golang/protobuf/proto/encode.go b/chaincode/abac/go/vendor/github.com/golang/protobuf/proto/encode.go index 8b84d1b2..3abfed2c 100644 --- a/chaincode/abac/go/vendor/github.com/golang/protobuf/proto/encode.go +++ b/chaincode/abac/go/vendor/github.com/golang/protobuf/proto/encode.go @@ -37,28 +37,9 @@ package proto import ( "errors" - "fmt" "reflect" - "sort" ) -// RequiredNotSetError is the error returned if Marshal is called with -// a protocol buffer struct whose required fields have not -// all been initialized. It is also the error returned if Unmarshal is -// called with an encoded protocol buffer that does not include all the -// required fields. -// -// When printed, RequiredNotSetError reports the first unset required field in a -// message. If the field cannot be precisely determined, it is reported as -// "{Unknown}". -type RequiredNotSetError struct { - field string -} - -func (e *RequiredNotSetError) Error() string { - return fmt.Sprintf("proto: required field %q not set", e.field) -} - var ( // errRepeatedHasNil is the error returned if Marshal is called with // a struct with a repeated field containing a nil element. @@ -82,10 +63,6 @@ var ( const maxVarintBytes = 10 // maximum length of a varint -// maxMarshalSize is the largest allowed size of an encoded protobuf, -// since C++ and Java use signed int32s for the size. -const maxMarshalSize = 1<<31 - 1 - // EncodeVarint returns the varint encoding of x. // This is the format for the // int32, int64, uint32, uint64, bool, and enum @@ -119,18 +96,27 @@ func (p *Buffer) EncodeVarint(x uint64) error { // SizeVarint returns the varint encoding size of an integer. func SizeVarint(x uint64) int { - return sizeVarint(x) -} - -func sizeVarint(x uint64) (n int) { - for { - n++ - x >>= 7 - if x == 0 { - break - } + switch { + case x < 1<<7: + return 1 + case x < 1<<14: + return 2 + case x < 1<<21: + return 3 + case x < 1<<28: + return 4 + case x < 1<<35: + return 5 + case x < 1<<42: + return 6 + case x < 1<<49: + return 7 + case x < 1<<56: + return 8 + case x < 1<<63: + return 9 } - return n + return 10 } // EncodeFixed64 writes a 64-bit integer to the Buffer. @@ -149,10 +135,6 @@ func (p *Buffer) EncodeFixed64(x uint64) error { return nil } -func sizeFixed64(x uint64) int { - return 8 -} - // EncodeFixed32 writes a 32-bit integer to the Buffer. // This is the format for the // fixed32, sfixed32, and float protocol buffer types. @@ -165,20 +147,12 @@ func (p *Buffer) EncodeFixed32(x uint64) error { return nil } -func sizeFixed32(x uint64) int { - return 4 -} - // EncodeZigzag64 writes a zigzag-encoded 64-bit integer // to the Buffer. // This is the format used for the sint64 protocol buffer type. func (p *Buffer) EncodeZigzag64(x uint64) error { // use signed number to get arithmetic right shift. - return p.EncodeVarint((x << 1) ^ uint64((int64(x) >> 63))) -} - -func sizeZigzag64(x uint64) int { - return sizeVarint((x << 1) ^ uint64((int64(x) >> 63))) + return p.EncodeVarint(uint64((x << 1) ^ uint64((int64(x) >> 63)))) } // EncodeZigzag32 writes a zigzag-encoded 32-bit integer @@ -189,10 +163,6 @@ func (p *Buffer) EncodeZigzag32(x uint64) error { return p.EncodeVarint(uint64((uint32(x) << 1) ^ uint32((int32(x) >> 31)))) } -func sizeZigzag32(x uint64) int { - return sizeVarint(uint64((uint32(x) << 1) ^ uint32((int32(x) >> 31)))) -} - // EncodeRawBytes writes a count-delimited byte buffer to the Buffer. // This is the format used for the bytes protocol buffer // type and for embedded messages. @@ -202,11 +172,6 @@ func (p *Buffer) EncodeRawBytes(b []byte) error { return nil } -func sizeRawBytes(b []byte) int { - return sizeVarint(uint64(len(b))) + - len(b) -} - // EncodeStringBytes writes an encoded string to the Buffer. // This is the format used for the proto2 string type. func (p *Buffer) EncodeStringBytes(s string) error { @@ -215,319 +180,17 @@ func (p *Buffer) EncodeStringBytes(s string) error { return nil } -func sizeStringBytes(s string) int { - return sizeVarint(uint64(len(s))) + - len(s) -} - // Marshaler is the interface representing objects that can marshal themselves. type Marshaler interface { Marshal() ([]byte, error) } -// Marshal takes the protocol buffer -// and encodes it into the wire format, returning the data. -func Marshal(pb Message) ([]byte, error) { - // Can the object marshal itself? - if m, ok := pb.(Marshaler); ok { - return m.Marshal() - } - p := NewBuffer(nil) - err := p.Marshal(pb) - if p.buf == nil && err == nil { - // Return a non-nil slice on success. - return []byte{}, nil - } - return p.buf, err -} - // EncodeMessage writes the protocol buffer to the Buffer, // prefixed by a varint-encoded length. func (p *Buffer) EncodeMessage(pb Message) error { - t, base, err := getbase(pb) - if structPointer_IsNil(base) { - return ErrNil - } - if err == nil { - var state errorState - err = p.enc_len_struct(GetProperties(t.Elem()), base, &state) - } - return err -} - -// Marshal takes the protocol buffer -// and encodes it into the wire format, writing the result to the -// Buffer. -func (p *Buffer) Marshal(pb Message) error { - // Can the object marshal itself? - if m, ok := pb.(Marshaler); ok { - data, err := m.Marshal() - p.buf = append(p.buf, data...) - return err - } - - t, base, err := getbase(pb) - if structPointer_IsNil(base) { - return ErrNil - } - if err == nil { - err = p.enc_struct(GetProperties(t.Elem()), base) - } - - if collectStats { - (stats).Encode++ // Parens are to work around a goimports bug. - } - - if len(p.buf) > maxMarshalSize { - return ErrTooLarge - } - return err -} - -// Size returns the encoded size of a protocol buffer. -func Size(pb Message) (n int) { - // Can the object marshal itself? If so, Size is slow. - // TODO: add Size to Marshaler, or add a Sizer interface. - if m, ok := pb.(Marshaler); ok { - b, _ := m.Marshal() - return len(b) - } - - t, base, err := getbase(pb) - if structPointer_IsNil(base) { - return 0 - } - if err == nil { - n = size_struct(GetProperties(t.Elem()), base) - } - - if collectStats { - (stats).Size++ // Parens are to work around a goimports bug. - } - - return -} - -// Individual type encoders. - -// Encode a bool. -func (o *Buffer) enc_bool(p *Properties, base structPointer) error { - v := *structPointer_Bool(base, p.field) - if v == nil { - return ErrNil - } - x := 0 - if *v { - x = 1 - } - o.buf = append(o.buf, p.tagcode...) - p.valEnc(o, uint64(x)) - return nil -} - -func (o *Buffer) enc_proto3_bool(p *Properties, base structPointer) error { - v := *structPointer_BoolVal(base, p.field) - if !v { - return ErrNil - } - o.buf = append(o.buf, p.tagcode...) - p.valEnc(o, 1) - return nil -} - -func size_bool(p *Properties, base structPointer) int { - v := *structPointer_Bool(base, p.field) - if v == nil { - return 0 - } - return len(p.tagcode) + 1 // each bool takes exactly one byte -} - -func size_proto3_bool(p *Properties, base structPointer) int { - v := *structPointer_BoolVal(base, p.field) - if !v && !p.oneof { - return 0 - } - return len(p.tagcode) + 1 // each bool takes exactly one byte -} - -// Encode an int32. -func (o *Buffer) enc_int32(p *Properties, base structPointer) error { - v := structPointer_Word32(base, p.field) - if word32_IsNil(v) { - return ErrNil - } - x := int32(word32_Get(v)) // permit sign extension to use full 64-bit range - o.buf = append(o.buf, p.tagcode...) - p.valEnc(o, uint64(x)) - return nil -} - -func (o *Buffer) enc_proto3_int32(p *Properties, base structPointer) error { - v := structPointer_Word32Val(base, p.field) - x := int32(word32Val_Get(v)) // permit sign extension to use full 64-bit range - if x == 0 { - return ErrNil - } - o.buf = append(o.buf, p.tagcode...) - p.valEnc(o, uint64(x)) - return nil -} - -func size_int32(p *Properties, base structPointer) (n int) { - v := structPointer_Word32(base, p.field) - if word32_IsNil(v) { - return 0 - } - x := int32(word32_Get(v)) // permit sign extension to use full 64-bit range - n += len(p.tagcode) - n += p.valSize(uint64(x)) - return -} - -func size_proto3_int32(p *Properties, base structPointer) (n int) { - v := structPointer_Word32Val(base, p.field) - x := int32(word32Val_Get(v)) // permit sign extension to use full 64-bit range - if x == 0 && !p.oneof { - return 0 - } - n += len(p.tagcode) - n += p.valSize(uint64(x)) - return -} - -// Encode a uint32. -// Exactly the same as int32, except for no sign extension. -func (o *Buffer) enc_uint32(p *Properties, base structPointer) error { - v := structPointer_Word32(base, p.field) - if word32_IsNil(v) { - return ErrNil - } - x := word32_Get(v) - o.buf = append(o.buf, p.tagcode...) - p.valEnc(o, uint64(x)) - return nil -} - -func (o *Buffer) enc_proto3_uint32(p *Properties, base structPointer) error { - v := structPointer_Word32Val(base, p.field) - x := word32Val_Get(v) - if x == 0 { - return ErrNil - } - o.buf = append(o.buf, p.tagcode...) - p.valEnc(o, uint64(x)) - return nil -} - -func size_uint32(p *Properties, base structPointer) (n int) { - v := structPointer_Word32(base, p.field) - if word32_IsNil(v) { - return 0 - } - x := word32_Get(v) - n += len(p.tagcode) - n += p.valSize(uint64(x)) - return -} - -func size_proto3_uint32(p *Properties, base structPointer) (n int) { - v := structPointer_Word32Val(base, p.field) - x := word32Val_Get(v) - if x == 0 && !p.oneof { - return 0 - } - n += len(p.tagcode) - n += p.valSize(uint64(x)) - return -} - -// Encode an int64. -func (o *Buffer) enc_int64(p *Properties, base structPointer) error { - v := structPointer_Word64(base, p.field) - if word64_IsNil(v) { - return ErrNil - } - x := word64_Get(v) - o.buf = append(o.buf, p.tagcode...) - p.valEnc(o, x) - return nil -} - -func (o *Buffer) enc_proto3_int64(p *Properties, base structPointer) error { - v := structPointer_Word64Val(base, p.field) - x := word64Val_Get(v) - if x == 0 { - return ErrNil - } - o.buf = append(o.buf, p.tagcode...) - p.valEnc(o, x) - return nil -} - -func size_int64(p *Properties, base structPointer) (n int) { - v := structPointer_Word64(base, p.field) - if word64_IsNil(v) { - return 0 - } - x := word64_Get(v) - n += len(p.tagcode) - n += p.valSize(x) - return -} - -func size_proto3_int64(p *Properties, base structPointer) (n int) { - v := structPointer_Word64Val(base, p.field) - x := word64Val_Get(v) - if x == 0 && !p.oneof { - return 0 - } - n += len(p.tagcode) - n += p.valSize(x) - return -} - -// Encode a string. -func (o *Buffer) enc_string(p *Properties, base structPointer) error { - v := *structPointer_String(base, p.field) - if v == nil { - return ErrNil - } - x := *v - o.buf = append(o.buf, p.tagcode...) - o.EncodeStringBytes(x) - return nil -} - -func (o *Buffer) enc_proto3_string(p *Properties, base structPointer) error { - v := *structPointer_StringVal(base, p.field) - if v == "" { - return ErrNil - } - o.buf = append(o.buf, p.tagcode...) - o.EncodeStringBytes(v) - return nil -} - -func size_string(p *Properties, base structPointer) (n int) { - v := *structPointer_String(base, p.field) - if v == nil { - return 0 - } - x := *v - n += len(p.tagcode) - n += sizeStringBytes(x) - return -} - -func size_proto3_string(p *Properties, base structPointer) (n int) { - v := *structPointer_StringVal(base, p.field) - if v == "" && !p.oneof { - return 0 - } - n += len(p.tagcode) - n += sizeStringBytes(v) - return + siz := Size(pb) + p.EncodeVarint(uint64(siz)) + return p.Marshal(pb) } // All protocol buffer fields are nillable, but be careful. @@ -538,825 +201,3 @@ func isNil(v reflect.Value) bool { } return false } - -// Encode a message struct. -func (o *Buffer) enc_struct_message(p *Properties, base structPointer) error { - var state errorState - structp := structPointer_GetStructPointer(base, p.field) - if structPointer_IsNil(structp) { - return ErrNil - } - - // Can the object marshal itself? - if p.isMarshaler { - m := structPointer_Interface(structp, p.stype).(Marshaler) - data, err := m.Marshal() - if err != nil && !state.shouldContinue(err, nil) { - return err - } - o.buf = append(o.buf, p.tagcode...) - o.EncodeRawBytes(data) - return state.err - } - - o.buf = append(o.buf, p.tagcode...) - return o.enc_len_struct(p.sprop, structp, &state) -} - -func size_struct_message(p *Properties, base structPointer) int { - structp := structPointer_GetStructPointer(base, p.field) - if structPointer_IsNil(structp) { - return 0 - } - - // Can the object marshal itself? - if p.isMarshaler { - m := structPointer_Interface(structp, p.stype).(Marshaler) - data, _ := m.Marshal() - n0 := len(p.tagcode) - n1 := sizeRawBytes(data) - return n0 + n1 - } - - n0 := len(p.tagcode) - n1 := size_struct(p.sprop, structp) - n2 := sizeVarint(uint64(n1)) // size of encoded length - return n0 + n1 + n2 -} - -// Encode a group struct. -func (o *Buffer) enc_struct_group(p *Properties, base structPointer) error { - var state errorState - b := structPointer_GetStructPointer(base, p.field) - if structPointer_IsNil(b) { - return ErrNil - } - - o.EncodeVarint(uint64((p.Tag << 3) | WireStartGroup)) - err := o.enc_struct(p.sprop, b) - if err != nil && !state.shouldContinue(err, nil) { - return err - } - o.EncodeVarint(uint64((p.Tag << 3) | WireEndGroup)) - return state.err -} - -func size_struct_group(p *Properties, base structPointer) (n int) { - b := structPointer_GetStructPointer(base, p.field) - if structPointer_IsNil(b) { - return 0 - } - - n += sizeVarint(uint64((p.Tag << 3) | WireStartGroup)) - n += size_struct(p.sprop, b) - n += sizeVarint(uint64((p.Tag << 3) | WireEndGroup)) - return -} - -// Encode a slice of bools ([]bool). -func (o *Buffer) enc_slice_bool(p *Properties, base structPointer) error { - s := *structPointer_BoolSlice(base, p.field) - l := len(s) - if l == 0 { - return ErrNil - } - for _, x := range s { - o.buf = append(o.buf, p.tagcode...) - v := uint64(0) - if x { - v = 1 - } - p.valEnc(o, v) - } - return nil -} - -func size_slice_bool(p *Properties, base structPointer) int { - s := *structPointer_BoolSlice(base, p.field) - l := len(s) - if l == 0 { - return 0 - } - return l * (len(p.tagcode) + 1) // each bool takes exactly one byte -} - -// Encode a slice of bools ([]bool) in packed format. -func (o *Buffer) enc_slice_packed_bool(p *Properties, base structPointer) error { - s := *structPointer_BoolSlice(base, p.field) - l := len(s) - if l == 0 { - return ErrNil - } - o.buf = append(o.buf, p.tagcode...) - o.EncodeVarint(uint64(l)) // each bool takes exactly one byte - for _, x := range s { - v := uint64(0) - if x { - v = 1 - } - p.valEnc(o, v) - } - return nil -} - -func size_slice_packed_bool(p *Properties, base structPointer) (n int) { - s := *structPointer_BoolSlice(base, p.field) - l := len(s) - if l == 0 { - return 0 - } - n += len(p.tagcode) - n += sizeVarint(uint64(l)) - n += l // each bool takes exactly one byte - return -} - -// Encode a slice of bytes ([]byte). -func (o *Buffer) enc_slice_byte(p *Properties, base structPointer) error { - s := *structPointer_Bytes(base, p.field) - if s == nil { - return ErrNil - } - o.buf = append(o.buf, p.tagcode...) - o.EncodeRawBytes(s) - return nil -} - -func (o *Buffer) enc_proto3_slice_byte(p *Properties, base structPointer) error { - s := *structPointer_Bytes(base, p.field) - if len(s) == 0 { - return ErrNil - } - o.buf = append(o.buf, p.tagcode...) - o.EncodeRawBytes(s) - return nil -} - -func size_slice_byte(p *Properties, base structPointer) (n int) { - s := *structPointer_Bytes(base, p.field) - if s == nil && !p.oneof { - return 0 - } - n += len(p.tagcode) - n += sizeRawBytes(s) - return -} - -func size_proto3_slice_byte(p *Properties, base structPointer) (n int) { - s := *structPointer_Bytes(base, p.field) - if len(s) == 0 && !p.oneof { - return 0 - } - n += len(p.tagcode) - n += sizeRawBytes(s) - return -} - -// Encode a slice of int32s ([]int32). -func (o *Buffer) enc_slice_int32(p *Properties, base structPointer) error { - s := structPointer_Word32Slice(base, p.field) - l := s.Len() - if l == 0 { - return ErrNil - } - for i := 0; i < l; i++ { - o.buf = append(o.buf, p.tagcode...) - x := int32(s.Index(i)) // permit sign extension to use full 64-bit range - p.valEnc(o, uint64(x)) - } - return nil -} - -func size_slice_int32(p *Properties, base structPointer) (n int) { - s := structPointer_Word32Slice(base, p.field) - l := s.Len() - if l == 0 { - return 0 - } - for i := 0; i < l; i++ { - n += len(p.tagcode) - x := int32(s.Index(i)) // permit sign extension to use full 64-bit range - n += p.valSize(uint64(x)) - } - return -} - -// Encode a slice of int32s ([]int32) in packed format. -func (o *Buffer) enc_slice_packed_int32(p *Properties, base structPointer) error { - s := structPointer_Word32Slice(base, p.field) - l := s.Len() - if l == 0 { - return ErrNil - } - // TODO: Reuse a Buffer. - buf := NewBuffer(nil) - for i := 0; i < l; i++ { - x := int32(s.Index(i)) // permit sign extension to use full 64-bit range - p.valEnc(buf, uint64(x)) - } - - o.buf = append(o.buf, p.tagcode...) - o.EncodeVarint(uint64(len(buf.buf))) - o.buf = append(o.buf, buf.buf...) - return nil -} - -func size_slice_packed_int32(p *Properties, base structPointer) (n int) { - s := structPointer_Word32Slice(base, p.field) - l := s.Len() - if l == 0 { - return 0 - } - var bufSize int - for i := 0; i < l; i++ { - x := int32(s.Index(i)) // permit sign extension to use full 64-bit range - bufSize += p.valSize(uint64(x)) - } - - n += len(p.tagcode) - n += sizeVarint(uint64(bufSize)) - n += bufSize - return -} - -// Encode a slice of uint32s ([]uint32). -// Exactly the same as int32, except for no sign extension. -func (o *Buffer) enc_slice_uint32(p *Properties, base structPointer) error { - s := structPointer_Word32Slice(base, p.field) - l := s.Len() - if l == 0 { - return ErrNil - } - for i := 0; i < l; i++ { - o.buf = append(o.buf, p.tagcode...) - x := s.Index(i) - p.valEnc(o, uint64(x)) - } - return nil -} - -func size_slice_uint32(p *Properties, base structPointer) (n int) { - s := structPointer_Word32Slice(base, p.field) - l := s.Len() - if l == 0 { - return 0 - } - for i := 0; i < l; i++ { - n += len(p.tagcode) - x := s.Index(i) - n += p.valSize(uint64(x)) - } - return -} - -// Encode a slice of uint32s ([]uint32) in packed format. -// Exactly the same as int32, except for no sign extension. -func (o *Buffer) enc_slice_packed_uint32(p *Properties, base structPointer) error { - s := structPointer_Word32Slice(base, p.field) - l := s.Len() - if l == 0 { - return ErrNil - } - // TODO: Reuse a Buffer. - buf := NewBuffer(nil) - for i := 0; i < l; i++ { - p.valEnc(buf, uint64(s.Index(i))) - } - - o.buf = append(o.buf, p.tagcode...) - o.EncodeVarint(uint64(len(buf.buf))) - o.buf = append(o.buf, buf.buf...) - return nil -} - -func size_slice_packed_uint32(p *Properties, base structPointer) (n int) { - s := structPointer_Word32Slice(base, p.field) - l := s.Len() - if l == 0 { - return 0 - } - var bufSize int - for i := 0; i < l; i++ { - bufSize += p.valSize(uint64(s.Index(i))) - } - - n += len(p.tagcode) - n += sizeVarint(uint64(bufSize)) - n += bufSize - return -} - -// Encode a slice of int64s ([]int64). -func (o *Buffer) enc_slice_int64(p *Properties, base structPointer) error { - s := structPointer_Word64Slice(base, p.field) - l := s.Len() - if l == 0 { - return ErrNil - } - for i := 0; i < l; i++ { - o.buf = append(o.buf, p.tagcode...) - p.valEnc(o, s.Index(i)) - } - return nil -} - -func size_slice_int64(p *Properties, base structPointer) (n int) { - s := structPointer_Word64Slice(base, p.field) - l := s.Len() - if l == 0 { - return 0 - } - for i := 0; i < l; i++ { - n += len(p.tagcode) - n += p.valSize(s.Index(i)) - } - return -} - -// Encode a slice of int64s ([]int64) in packed format. -func (o *Buffer) enc_slice_packed_int64(p *Properties, base structPointer) error { - s := structPointer_Word64Slice(base, p.field) - l := s.Len() - if l == 0 { - return ErrNil - } - // TODO: Reuse a Buffer. - buf := NewBuffer(nil) - for i := 0; i < l; i++ { - p.valEnc(buf, s.Index(i)) - } - - o.buf = append(o.buf, p.tagcode...) - o.EncodeVarint(uint64(len(buf.buf))) - o.buf = append(o.buf, buf.buf...) - return nil -} - -func size_slice_packed_int64(p *Properties, base structPointer) (n int) { - s := structPointer_Word64Slice(base, p.field) - l := s.Len() - if l == 0 { - return 0 - } - var bufSize int - for i := 0; i < l; i++ { - bufSize += p.valSize(s.Index(i)) - } - - n += len(p.tagcode) - n += sizeVarint(uint64(bufSize)) - n += bufSize - return -} - -// Encode a slice of slice of bytes ([][]byte). -func (o *Buffer) enc_slice_slice_byte(p *Properties, base structPointer) error { - ss := *structPointer_BytesSlice(base, p.field) - l := len(ss) - if l == 0 { - return ErrNil - } - for i := 0; i < l; i++ { - o.buf = append(o.buf, p.tagcode...) - o.EncodeRawBytes(ss[i]) - } - return nil -} - -func size_slice_slice_byte(p *Properties, base structPointer) (n int) { - ss := *structPointer_BytesSlice(base, p.field) - l := len(ss) - if l == 0 { - return 0 - } - n += l * len(p.tagcode) - for i := 0; i < l; i++ { - n += sizeRawBytes(ss[i]) - } - return -} - -// Encode a slice of strings ([]string). -func (o *Buffer) enc_slice_string(p *Properties, base structPointer) error { - ss := *structPointer_StringSlice(base, p.field) - l := len(ss) - for i := 0; i < l; i++ { - o.buf = append(o.buf, p.tagcode...) - o.EncodeStringBytes(ss[i]) - } - return nil -} - -func size_slice_string(p *Properties, base structPointer) (n int) { - ss := *structPointer_StringSlice(base, p.field) - l := len(ss) - n += l * len(p.tagcode) - for i := 0; i < l; i++ { - n += sizeStringBytes(ss[i]) - } - return -} - -// Encode a slice of message structs ([]*struct). -func (o *Buffer) enc_slice_struct_message(p *Properties, base structPointer) error { - var state errorState - s := structPointer_StructPointerSlice(base, p.field) - l := s.Len() - - for i := 0; i < l; i++ { - structp := s.Index(i) - if structPointer_IsNil(structp) { - return errRepeatedHasNil - } - - // Can the object marshal itself? - if p.isMarshaler { - m := structPointer_Interface(structp, p.stype).(Marshaler) - data, err := m.Marshal() - if err != nil && !state.shouldContinue(err, nil) { - return err - } - o.buf = append(o.buf, p.tagcode...) - o.EncodeRawBytes(data) - continue - } - - o.buf = append(o.buf, p.tagcode...) - err := o.enc_len_struct(p.sprop, structp, &state) - if err != nil && !state.shouldContinue(err, nil) { - if err == ErrNil { - return errRepeatedHasNil - } - return err - } - } - return state.err -} - -func size_slice_struct_message(p *Properties, base structPointer) (n int) { - s := structPointer_StructPointerSlice(base, p.field) - l := s.Len() - n += l * len(p.tagcode) - for i := 0; i < l; i++ { - structp := s.Index(i) - if structPointer_IsNil(structp) { - return // return the size up to this point - } - - // Can the object marshal itself? - if p.isMarshaler { - m := structPointer_Interface(structp, p.stype).(Marshaler) - data, _ := m.Marshal() - n += sizeRawBytes(data) - continue - } - - n0 := size_struct(p.sprop, structp) - n1 := sizeVarint(uint64(n0)) // size of encoded length - n += n0 + n1 - } - return -} - -// Encode a slice of group structs ([]*struct). -func (o *Buffer) enc_slice_struct_group(p *Properties, base structPointer) error { - var state errorState - s := structPointer_StructPointerSlice(base, p.field) - l := s.Len() - - for i := 0; i < l; i++ { - b := s.Index(i) - if structPointer_IsNil(b) { - return errRepeatedHasNil - } - - o.EncodeVarint(uint64((p.Tag << 3) | WireStartGroup)) - - err := o.enc_struct(p.sprop, b) - - if err != nil && !state.shouldContinue(err, nil) { - if err == ErrNil { - return errRepeatedHasNil - } - return err - } - - o.EncodeVarint(uint64((p.Tag << 3) | WireEndGroup)) - } - return state.err -} - -func size_slice_struct_group(p *Properties, base structPointer) (n int) { - s := structPointer_StructPointerSlice(base, p.field) - l := s.Len() - - n += l * sizeVarint(uint64((p.Tag<<3)|WireStartGroup)) - n += l * sizeVarint(uint64((p.Tag<<3)|WireEndGroup)) - for i := 0; i < l; i++ { - b := s.Index(i) - if structPointer_IsNil(b) { - return // return size up to this point - } - - n += size_struct(p.sprop, b) - } - return -} - -// Encode an extension map. -func (o *Buffer) enc_map(p *Properties, base structPointer) error { - exts := structPointer_ExtMap(base, p.field) - if err := encodeExtensionsMap(*exts); err != nil { - return err - } - - return o.enc_map_body(*exts) -} - -func (o *Buffer) enc_exts(p *Properties, base structPointer) error { - exts := structPointer_Extensions(base, p.field) - - v, mu := exts.extensionsRead() - if v == nil { - return nil - } - - mu.Lock() - defer mu.Unlock() - if err := encodeExtensionsMap(v); err != nil { - return err - } - - return o.enc_map_body(v) -} - -func (o *Buffer) enc_map_body(v map[int32]Extension) error { - // Fast-path for common cases: zero or one extensions. - if len(v) <= 1 { - for _, e := range v { - o.buf = append(o.buf, e.enc...) - } - return nil - } - - // Sort keys to provide a deterministic encoding. - keys := make([]int, 0, len(v)) - for k := range v { - keys = append(keys, int(k)) - } - sort.Ints(keys) - - for _, k := range keys { - o.buf = append(o.buf, v[int32(k)].enc...) - } - return nil -} - -func size_map(p *Properties, base structPointer) int { - v := structPointer_ExtMap(base, p.field) - return extensionsMapSize(*v) -} - -func size_exts(p *Properties, base structPointer) int { - v := structPointer_Extensions(base, p.field) - return extensionsSize(v) -} - -// Encode a map field. -func (o *Buffer) enc_new_map(p *Properties, base structPointer) error { - var state errorState // XXX: or do we need to plumb this through? - - /* - A map defined as - map map_field = N; - is encoded in the same way as - message MapFieldEntry { - key_type key = 1; - value_type value = 2; - } - repeated MapFieldEntry map_field = N; - */ - - v := structPointer_NewAt(base, p.field, p.mtype).Elem() // map[K]V - if v.Len() == 0 { - return nil - } - - keycopy, valcopy, keybase, valbase := mapEncodeScratch(p.mtype) - - enc := func() error { - if err := p.mkeyprop.enc(o, p.mkeyprop, keybase); err != nil { - return err - } - if err := p.mvalprop.enc(o, p.mvalprop, valbase); err != nil && err != ErrNil { - return err - } - return nil - } - - // Don't sort map keys. It is not required by the spec, and C++ doesn't do it. - for _, key := range v.MapKeys() { - val := v.MapIndex(key) - - keycopy.Set(key) - valcopy.Set(val) - - o.buf = append(o.buf, p.tagcode...) - if err := o.enc_len_thing(enc, &state); err != nil { - return err - } - } - return nil -} - -func size_new_map(p *Properties, base structPointer) int { - v := structPointer_NewAt(base, p.field, p.mtype).Elem() // map[K]V - - keycopy, valcopy, keybase, valbase := mapEncodeScratch(p.mtype) - - n := 0 - for _, key := range v.MapKeys() { - val := v.MapIndex(key) - keycopy.Set(key) - valcopy.Set(val) - - // Tag codes for key and val are the responsibility of the sub-sizer. - keysize := p.mkeyprop.size(p.mkeyprop, keybase) - valsize := p.mvalprop.size(p.mvalprop, valbase) - entry := keysize + valsize - // Add on tag code and length of map entry itself. - n += len(p.tagcode) + sizeVarint(uint64(entry)) + entry - } - return n -} - -// mapEncodeScratch returns a new reflect.Value matching the map's value type, -// and a structPointer suitable for passing to an encoder or sizer. -func mapEncodeScratch(mapType reflect.Type) (keycopy, valcopy reflect.Value, keybase, valbase structPointer) { - // Prepare addressable doubly-indirect placeholders for the key and value types. - // This is needed because the element-type encoders expect **T, but the map iteration produces T. - - keycopy = reflect.New(mapType.Key()).Elem() // addressable K - keyptr := reflect.New(reflect.PtrTo(keycopy.Type())).Elem() // addressable *K - keyptr.Set(keycopy.Addr()) // - keybase = toStructPointer(keyptr.Addr()) // **K - - // Value types are more varied and require special handling. - switch mapType.Elem().Kind() { - case reflect.Slice: - // []byte - var dummy []byte - valcopy = reflect.ValueOf(&dummy).Elem() // addressable []byte - valbase = toStructPointer(valcopy.Addr()) - case reflect.Ptr: - // message; the generated field type is map[K]*Msg (so V is *Msg), - // so we only need one level of indirection. - valcopy = reflect.New(mapType.Elem()).Elem() // addressable V - valbase = toStructPointer(valcopy.Addr()) - default: - // everything else - valcopy = reflect.New(mapType.Elem()).Elem() // addressable V - valptr := reflect.New(reflect.PtrTo(valcopy.Type())).Elem() // addressable *V - valptr.Set(valcopy.Addr()) // - valbase = toStructPointer(valptr.Addr()) // **V - } - return -} - -// Encode a struct. -func (o *Buffer) enc_struct(prop *StructProperties, base structPointer) error { - var state errorState - // Encode fields in tag order so that decoders may use optimizations - // that depend on the ordering. - // https://developers.google.com/protocol-buffers/docs/encoding#order - for _, i := range prop.order { - p := prop.Prop[i] - if p.enc != nil { - err := p.enc(o, p, base) - if err != nil { - if err == ErrNil { - if p.Required && state.err == nil { - state.err = &RequiredNotSetError{p.Name} - } - } else if err == errRepeatedHasNil { - // Give more context to nil values in repeated fields. - return errors.New("repeated field " + p.OrigName + " has nil element") - } else if !state.shouldContinue(err, p) { - return err - } - } - if len(o.buf) > maxMarshalSize { - return ErrTooLarge - } - } - } - - // Do oneof fields. - if prop.oneofMarshaler != nil { - m := structPointer_Interface(base, prop.stype).(Message) - if err := prop.oneofMarshaler(m, o); err == ErrNil { - return errOneofHasNil - } else if err != nil { - return err - } - } - - // Add unrecognized fields at the end. - if prop.unrecField.IsValid() { - v := *structPointer_Bytes(base, prop.unrecField) - if len(o.buf)+len(v) > maxMarshalSize { - return ErrTooLarge - } - if len(v) > 0 { - o.buf = append(o.buf, v...) - } - } - - return state.err -} - -func size_struct(prop *StructProperties, base structPointer) (n int) { - for _, i := range prop.order { - p := prop.Prop[i] - if p.size != nil { - n += p.size(p, base) - } - } - - // Add unrecognized fields at the end. - if prop.unrecField.IsValid() { - v := *structPointer_Bytes(base, prop.unrecField) - n += len(v) - } - - // Factor in any oneof fields. - if prop.oneofSizer != nil { - m := structPointer_Interface(base, prop.stype).(Message) - n += prop.oneofSizer(m) - } - - return -} - -var zeroes [20]byte // longer than any conceivable sizeVarint - -// Encode a struct, preceded by its encoded length (as a varint). -func (o *Buffer) enc_len_struct(prop *StructProperties, base structPointer, state *errorState) error { - return o.enc_len_thing(func() error { return o.enc_struct(prop, base) }, state) -} - -// Encode something, preceded by its encoded length (as a varint). -func (o *Buffer) enc_len_thing(enc func() error, state *errorState) error { - iLen := len(o.buf) - o.buf = append(o.buf, 0, 0, 0, 0) // reserve four bytes for length - iMsg := len(o.buf) - err := enc() - if err != nil && !state.shouldContinue(err, nil) { - return err - } - lMsg := len(o.buf) - iMsg - lLen := sizeVarint(uint64(lMsg)) - switch x := lLen - (iMsg - iLen); { - case x > 0: // actual length is x bytes larger than the space we reserved - // Move msg x bytes right. - o.buf = append(o.buf, zeroes[:x]...) - copy(o.buf[iMsg+x:], o.buf[iMsg:iMsg+lMsg]) - case x < 0: // actual length is x bytes smaller than the space we reserved - // Move msg x bytes left. - copy(o.buf[iMsg+x:], o.buf[iMsg:iMsg+lMsg]) - o.buf = o.buf[:len(o.buf)+x] // x is negative - } - // Encode the length in the reserved space. - o.buf = o.buf[:iLen] - o.EncodeVarint(uint64(lMsg)) - o.buf = o.buf[:len(o.buf)+lMsg] - return state.err -} - -// errorState maintains the first error that occurs and updates that error -// with additional context. -type errorState struct { - err error -} - -// shouldContinue reports whether encoding should continue upon encountering the -// given error. If the error is RequiredNotSetError, shouldContinue returns true -// and, if this is the first appearance of that error, remembers it for future -// reporting. -// -// If prop is not nil, it may update any error with additional context about the -// field with the error. -func (s *errorState) shouldContinue(err error, prop *Properties) bool { - // Ignore unset required fields. - reqNotSet, ok := err.(*RequiredNotSetError) - if !ok { - return false - } - if s.err == nil { - if prop != nil { - err = &RequiredNotSetError{prop.Name + "." + reqNotSet.field} - } - s.err = err - } - return true -} diff --git a/chaincode/abac/go/vendor/github.com/golang/protobuf/proto/equal.go b/chaincode/abac/go/vendor/github.com/golang/protobuf/proto/equal.go index 2ed1cf59..d4db5a1c 100644 --- a/chaincode/abac/go/vendor/github.com/golang/protobuf/proto/equal.go +++ b/chaincode/abac/go/vendor/github.com/golang/protobuf/proto/equal.go @@ -109,15 +109,6 @@ func equalStruct(v1, v2 reflect.Value) bool { // set/unset mismatch return false } - b1, ok := f1.Interface().(raw) - if ok { - b2 := f2.Interface().(raw) - // RawMessage - if !bytes.Equal(b1.Bytes(), b2.Bytes()) { - return false - } - continue - } f1, f2 = f1.Elem(), f2.Elem() } if !equalAny(f1, f2, sprop.Prop[i]) { @@ -146,11 +137,7 @@ func equalStruct(v1, v2 reflect.Value) bool { u1 := uf.Bytes() u2 := v2.FieldByName("XXX_unrecognized").Bytes() - if !bytes.Equal(u1, u2) { - return false - } - - return true + return bytes.Equal(u1, u2) } // v1 and v2 are known to have the same type. @@ -261,6 +248,15 @@ func equalExtMap(base reflect.Type, em1, em2 map[int32]Extension) bool { m1, m2 := e1.value, e2.value + if m1 == nil && m2 == nil { + // Both have only encoded form. + if bytes.Equal(e1.enc, e2.enc) { + continue + } + // The bytes are different, but the extensions might still be + // equal. We need to decode them to compare. + } + if m1 != nil && m2 != nil { // Both are unencoded. if !equalAny(reflect.ValueOf(m1), reflect.ValueOf(m2), nil) { @@ -276,8 +272,12 @@ func equalExtMap(base reflect.Type, em1, em2 map[int32]Extension) bool { desc = m[extNum] } if desc == nil { + // If both have only encoded form and the bytes are the same, + // it is handled above. We get here when the bytes are different. + // We don't know how to decode it, so just compare them as byte + // slices. log.Printf("proto: don't know how to compare extension %d of %v", extNum, base) - continue + return false } var err error if m1 == nil { diff --git a/chaincode/abac/go/vendor/github.com/golang/protobuf/proto/extensions.go b/chaincode/abac/go/vendor/github.com/golang/protobuf/proto/extensions.go index eaad2183..dacdd22d 100644 --- a/chaincode/abac/go/vendor/github.com/golang/protobuf/proto/extensions.go +++ b/chaincode/abac/go/vendor/github.com/golang/protobuf/proto/extensions.go @@ -38,6 +38,7 @@ package proto import ( "errors" "fmt" + "io" "reflect" "strconv" "sync" @@ -91,14 +92,29 @@ func (n notLocker) Unlock() {} // extendable returns the extendableProto interface for the given generated proto message. // If the proto message has the old extension format, it returns a wrapper that implements // the extendableProto interface. -func extendable(p interface{}) (extendableProto, bool) { - if ep, ok := p.(extendableProto); ok { - return ep, ok +func extendable(p interface{}) (extendableProto, error) { + switch p := p.(type) { + case extendableProto: + if isNilPtr(p) { + return nil, fmt.Errorf("proto: nil %T is not extendable", p) + } + return p, nil + case extendableProtoV1: + if isNilPtr(p) { + return nil, fmt.Errorf("proto: nil %T is not extendable", p) + } + return extensionAdapter{p}, nil } - if ep, ok := p.(extendableProtoV1); ok { - return extensionAdapter{ep}, ok - } - return nil, false + // Don't allocate a specific error containing %T: + // this is the hot path for Clone and MarshalText. + return nil, errNotExtendable +} + +var errNotExtendable = errors.New("proto: not an extendable proto.Message") + +func isNilPtr(x interface{}) bool { + v := reflect.ValueOf(x) + return v.Kind() == reflect.Ptr && v.IsNil() } // XXX_InternalExtensions is an internal representation of proto extensions. @@ -143,9 +159,6 @@ func (e *XXX_InternalExtensions) extensionsRead() (map[int32]Extension, sync.Loc return e.p.extensionMap, &e.p.mu } -var extendableProtoType = reflect.TypeOf((*extendableProto)(nil)).Elem() -var extendableProtoV1Type = reflect.TypeOf((*extendableProtoV1)(nil)).Elem() - // ExtensionDesc represents an extension specification. // Used in generated code from the protocol compiler. type ExtensionDesc struct { @@ -179,8 +192,8 @@ type Extension struct { // SetRawExtension is for testing only. func SetRawExtension(base Message, id int32, b []byte) { - epb, ok := extendable(base) - if !ok { + epb, err := extendable(base) + if err != nil { return } extmap := epb.extensionsWrite() @@ -205,7 +218,7 @@ func checkExtensionTypes(pb extendableProto, extension *ExtensionDesc) error { pbi = ea.extendableProtoV1 } if a, b := reflect.TypeOf(pbi), reflect.TypeOf(extension.ExtendedType); a != b { - return errors.New("proto: bad extended type; " + b.String() + " does not extend " + a.String()) + return fmt.Errorf("proto: bad extended type; %v does not extend %v", b, a) } // Check the range. if !isExtensionField(pb, extension.Field) { @@ -250,85 +263,11 @@ func extensionProperties(ed *ExtensionDesc) *Properties { return prop } -// encode encodes any unmarshaled (unencoded) extensions in e. -func encodeExtensions(e *XXX_InternalExtensions) error { - m, mu := e.extensionsRead() - if m == nil { - return nil // fast path - } - mu.Lock() - defer mu.Unlock() - return encodeExtensionsMap(m) -} - -// encode encodes any unmarshaled (unencoded) extensions in e. -func encodeExtensionsMap(m map[int32]Extension) error { - for k, e := range m { - if e.value == nil || e.desc == nil { - // Extension is only in its encoded form. - continue - } - - // We don't skip extensions that have an encoded form set, - // because the extension value may have been mutated after - // the last time this function was called. - - et := reflect.TypeOf(e.desc.ExtensionType) - props := extensionProperties(e.desc) - - p := NewBuffer(nil) - // If e.value has type T, the encoder expects a *struct{ X T }. - // Pass a *T with a zero field and hope it all works out. - x := reflect.New(et) - x.Elem().Set(reflect.ValueOf(e.value)) - if err := props.enc(p, props, toStructPointer(x)); err != nil { - return err - } - e.enc = p.buf - m[k] = e - } - return nil -} - -func extensionsSize(e *XXX_InternalExtensions) (n int) { - m, mu := e.extensionsRead() - if m == nil { - return 0 - } - mu.Lock() - defer mu.Unlock() - return extensionsMapSize(m) -} - -func extensionsMapSize(m map[int32]Extension) (n int) { - for _, e := range m { - if e.value == nil || e.desc == nil { - // Extension is only in its encoded form. - n += len(e.enc) - continue - } - - // We don't skip extensions that have an encoded form set, - // because the extension value may have been mutated after - // the last time this function was called. - - et := reflect.TypeOf(e.desc.ExtensionType) - props := extensionProperties(e.desc) - - // If e.value has type T, the encoder expects a *struct{ X T }. - // Pass a *T with a zero field and hope it all works out. - x := reflect.New(et) - x.Elem().Set(reflect.ValueOf(e.value)) - n += props.size(props, toStructPointer(x)) - } - return -} - // HasExtension returns whether the given extension is present in pb. func HasExtension(pb Message, extension *ExtensionDesc) bool { // TODO: Check types, field numbers, etc.? - epb, ok := extendable(pb) - if !ok { + epb, err := extendable(pb) + if err != nil { return false } extmap, mu := epb.extensionsRead() @@ -336,15 +275,15 @@ func HasExtension(pb Message, extension *ExtensionDesc) bool { return false } mu.Lock() - _, ok = extmap[extension.Field] + _, ok := extmap[extension.Field] mu.Unlock() return ok } // ClearExtension removes the given extension from pb. func ClearExtension(pb Message, extension *ExtensionDesc) { - epb, ok := extendable(pb) - if !ok { + epb, err := extendable(pb) + if err != nil { return } // TODO: Check types, field numbers, etc.? @@ -352,16 +291,26 @@ func ClearExtension(pb Message, extension *ExtensionDesc) { delete(extmap, extension.Field) } -// GetExtension parses and returns the given extension of pb. -// If the extension is not present and has no default value it returns ErrMissingExtension. +// GetExtension retrieves a proto2 extended field from pb. +// +// If the descriptor is type complete (i.e., ExtensionDesc.ExtensionType is non-nil), +// then GetExtension parses the encoded field and returns a Go value of the specified type. +// If the field is not present, then the default value is returned (if one is specified), +// otherwise ErrMissingExtension is reported. +// +// If the descriptor is not type complete (i.e., ExtensionDesc.ExtensionType is nil), +// then GetExtension returns the raw encoded bytes of the field extension. func GetExtension(pb Message, extension *ExtensionDesc) (interface{}, error) { - epb, ok := extendable(pb) - if !ok { - return nil, errors.New("proto: not an extendable proto") + epb, err := extendable(pb) + if err != nil { + return nil, err } - if err := checkExtensionTypes(epb, extension); err != nil { - return nil, err + if extension.ExtendedType != nil { + // can only check type if this is a complete descriptor + if err := checkExtensionTypes(epb, extension); err != nil { + return nil, err + } } emap, mu := epb.extensionsRead() @@ -388,6 +337,11 @@ func GetExtension(pb Message, extension *ExtensionDesc) (interface{}, error) { return e.value, nil } + if extension.ExtensionType == nil { + // incomplete descriptor + return e.enc, nil + } + v, err := decodeExtension(e.enc, extension) if err != nil { return nil, err @@ -405,6 +359,11 @@ func GetExtension(pb Message, extension *ExtensionDesc) (interface{}, error) { // defaultExtensionValue returns the default value for extension. // If no default for an extension is defined ErrMissingExtension is returned. func defaultExtensionValue(extension *ExtensionDesc) (interface{}, error) { + if extension.ExtensionType == nil { + // incomplete descriptor, so no default + return nil, ErrMissingExtension + } + t := reflect.TypeOf(extension.ExtensionType) props := extensionProperties(extension) @@ -439,31 +398,28 @@ func defaultExtensionValue(extension *ExtensionDesc) (interface{}, error) { // decodeExtension decodes an extension encoded in b. func decodeExtension(b []byte, extension *ExtensionDesc) (interface{}, error) { - o := NewBuffer(b) - t := reflect.TypeOf(extension.ExtensionType) - - props := extensionProperties(extension) + unmarshal := typeUnmarshaler(t, extension.Tag) // t is a pointer to a struct, pointer to basic type or a slice. - // Allocate a "field" to store the pointer/slice itself; the - // pointer/slice will be stored here. We pass - // the address of this field to props.dec. - // This passes a zero field and a *t and lets props.dec - // interpret it as a *struct{ x t }. + // Allocate space to store the pointer/slice. value := reflect.New(t).Elem() + var err error for { - // Discard wire type and field number varint. It isn't needed. - if _, err := o.DecodeVarint(); err != nil { + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + wire := int(x) & 7 + + b, err = unmarshal(b, valToPointer(value.Addr()), wire) + if err != nil { return nil, err } - if err := props.dec(o, props, toStructPointer(value.Addr())); err != nil { - return nil, err - } - - if o.index >= len(o.buf) { + if len(b) == 0 { break } } @@ -473,9 +429,9 @@ func decodeExtension(b []byte, extension *ExtensionDesc) (interface{}, error) { // GetExtensions returns a slice of the extensions present in pb that are also listed in es. // The returned slice has the same length as es; missing extensions will appear as nil elements. func GetExtensions(pb Message, es []*ExtensionDesc) (extensions []interface{}, err error) { - epb, ok := extendable(pb) - if !ok { - return nil, errors.New("proto: not an extendable proto") + epb, err := extendable(pb) + if err != nil { + return nil, err } extensions = make([]interface{}, len(es)) for i, e := range es { @@ -494,9 +450,9 @@ func GetExtensions(pb Message, es []*ExtensionDesc) (extensions []interface{}, e // For non-registered extensions, ExtensionDescs returns an incomplete descriptor containing // just the Field field, which defines the extension's field number. func ExtensionDescs(pb Message) ([]*ExtensionDesc, error) { - epb, ok := extendable(pb) - if !ok { - return nil, fmt.Errorf("proto: %T is not an extendable proto.Message", pb) + epb, err := extendable(pb) + if err != nil { + return nil, err } registeredExtensions := RegisteredExtensions(pb) @@ -523,16 +479,16 @@ func ExtensionDescs(pb Message) ([]*ExtensionDesc, error) { // SetExtension sets the specified extension of pb to the specified value. func SetExtension(pb Message, extension *ExtensionDesc, value interface{}) error { - epb, ok := extendable(pb) - if !ok { - return errors.New("proto: not an extendable proto") + epb, err := extendable(pb) + if err != nil { + return err } if err := checkExtensionTypes(epb, extension); err != nil { return err } typ := reflect.TypeOf(extension.ExtensionType) if typ != reflect.TypeOf(value) { - return errors.New("proto: bad extension value type") + return fmt.Errorf("proto: bad extension value type. got: %T, want: %T", value, extension.ExtensionType) } // nil extension values need to be caught early, because the // encoder can't distinguish an ErrNil due to a nil extension @@ -550,8 +506,8 @@ func SetExtension(pb Message, extension *ExtensionDesc, value interface{}) error // ClearAllExtensions clears all extensions from pb. func ClearAllExtensions(pb Message) { - epb, ok := extendable(pb) - if !ok { + epb, err := extendable(pb) + if err != nil { return } m := epb.extensionsWrite() diff --git a/chaincode/abac/go/vendor/github.com/golang/protobuf/proto/lib.go b/chaincode/abac/go/vendor/github.com/golang/protobuf/proto/lib.go index 1c225504..c076dbdb 100644 --- a/chaincode/abac/go/vendor/github.com/golang/protobuf/proto/lib.go +++ b/chaincode/abac/go/vendor/github.com/golang/protobuf/proto/lib.go @@ -273,6 +273,67 @@ import ( "sync" ) +// RequiredNotSetError is an error type returned by either Marshal or Unmarshal. +// Marshal reports this when a required field is not initialized. +// Unmarshal reports this when a required field is missing from the wire data. +type RequiredNotSetError struct{ field string } + +func (e *RequiredNotSetError) Error() string { + if e.field == "" { + return fmt.Sprintf("proto: required field not set") + } + return fmt.Sprintf("proto: required field %q not set", e.field) +} +func (e *RequiredNotSetError) RequiredNotSet() bool { + return true +} + +type invalidUTF8Error struct{ field string } + +func (e *invalidUTF8Error) Error() string { + if e.field == "" { + return "proto: invalid UTF-8 detected" + } + return fmt.Sprintf("proto: field %q contains invalid UTF-8", e.field) +} +func (e *invalidUTF8Error) InvalidUTF8() bool { + return true +} + +// errInvalidUTF8 is a sentinel error to identify fields with invalid UTF-8. +// This error should not be exposed to the external API as such errors should +// be recreated with the field information. +var errInvalidUTF8 = &invalidUTF8Error{} + +// isNonFatal reports whether the error is either a RequiredNotSet error +// or a InvalidUTF8 error. +func isNonFatal(err error) bool { + if re, ok := err.(interface{ RequiredNotSet() bool }); ok && re.RequiredNotSet() { + return true + } + if re, ok := err.(interface{ InvalidUTF8() bool }); ok && re.InvalidUTF8() { + return true + } + return false +} + +type nonFatal struct{ E error } + +// Merge merges err into nf and reports whether it was successful. +// Otherwise it returns false for any fatal non-nil errors. +func (nf *nonFatal) Merge(err error) (ok bool) { + if err == nil { + return true // not an error + } + if !isNonFatal(err) { + return false // fatal error + } + if nf.E == nil { + nf.E = err // store first instance of non-fatal error + } + return true +} + // Message is implemented by generated protocol buffer messages. type Message interface { Reset() @@ -280,26 +341,6 @@ type Message interface { ProtoMessage() } -// Stats records allocation details about the protocol buffer encoders -// and decoders. Useful for tuning the library itself. -type Stats struct { - Emalloc uint64 // mallocs in encode - Dmalloc uint64 // mallocs in decode - Encode uint64 // number of encodes - Decode uint64 // number of decodes - Chit uint64 // number of cache hits - Cmiss uint64 // number of cache misses - Size uint64 // number of sizes -} - -// Set to true to enable stats collection. -const collectStats = false - -var stats Stats - -// GetStats returns a copy of the global Stats structure. -func GetStats() Stats { return stats } - // A Buffer is a buffer manager for marshaling and unmarshaling // protocol buffers. It may be reused between invocations to // reduce memory usage. It is not necessary to use a Buffer; @@ -309,16 +350,7 @@ type Buffer struct { buf []byte // encode/decode byte stream index int // read point - // pools of basic types to amortize allocation. - bools []bool - uint32s []uint32 - uint64s []uint64 - - // extra pools, only used with pointer_reflect.go - int32s []int32 - int64s []int64 - float32s []float32 - float64s []float64 + deterministic bool } // NewBuffer allocates a new Buffer and initializes its internal data to @@ -343,6 +375,30 @@ func (p *Buffer) SetBuf(s []byte) { // Bytes returns the contents of the Buffer. func (p *Buffer) Bytes() []byte { return p.buf } +// SetDeterministic sets whether to use deterministic serialization. +// +// Deterministic serialization guarantees that for a given binary, equal +// messages will always be serialized to the same bytes. This implies: +// +// - Repeated serialization of a message will return the same bytes. +// - Different processes of the same binary (which may be executing on +// different machines) will serialize equal messages to the same bytes. +// +// Note that the deterministic serialization is NOT canonical across +// languages. It is not guaranteed to remain stable over time. It is unstable +// across different builds with schema changes due to unknown fields. +// Users who need canonical serialization (e.g., persistent storage in a +// canonical form, fingerprinting, etc.) should define their own +// canonicalization specification and implement their own serializer rather +// than relying on this API. +// +// If deterministic serialization is requested, map entries will be sorted +// by keys in lexographical order. This is an implementation detail and +// subject to change. +func (p *Buffer) SetDeterministic(deterministic bool) { + p.deterministic = deterministic +} + /* * Helper routines for simplifying the creation of optional fields of basic type. */ @@ -831,22 +887,12 @@ func fieldDefault(ft reflect.Type, prop *Properties) (sf *scalarField, nestedMes return sf, false, nil } +// mapKeys returns a sort.Interface to be used for sorting the map keys. // Map fields may have key types of non-float scalars, strings and enums. -// The easiest way to sort them in some deterministic order is to use fmt. -// If this turns out to be inefficient we can always consider other options, -// such as doing a Schwartzian transform. - func mapKeys(vs []reflect.Value) sort.Interface { - s := mapKeySorter{ - vs: vs, - // default Less function: textual comparison - less: func(a, b reflect.Value) bool { - return fmt.Sprint(a.Interface()) < fmt.Sprint(b.Interface()) - }, - } + s := mapKeySorter{vs: vs} - // Type specialization per https://developers.google.com/protocol-buffers/docs/proto#maps; - // numeric keys are sorted numerically. + // Type specialization per https://developers.google.com/protocol-buffers/docs/proto#maps. if len(vs) == 0 { return s } @@ -855,6 +901,12 @@ func mapKeys(vs []reflect.Value) sort.Interface { s.less = func(a, b reflect.Value) bool { return a.Int() < b.Int() } case reflect.Uint32, reflect.Uint64: s.less = func(a, b reflect.Value) bool { return a.Uint() < b.Uint() } + case reflect.Bool: + s.less = func(a, b reflect.Value) bool { return !a.Bool() && b.Bool() } // false < true + case reflect.String: + s.less = func(a, b reflect.Value) bool { return a.String() < b.String() } + default: + panic(fmt.Sprintf("unsupported map key type: %v", vs[0].Kind())) } return s @@ -895,3 +947,13 @@ const ProtoPackageIsVersion2 = true // ProtoPackageIsVersion1 is referenced from generated protocol buffer files // to assert that that code is compatible with this version of the proto package. const ProtoPackageIsVersion1 = true + +// InternalMessageInfo is a type used internally by generated .pb.go files. +// This type is not intended to be used by non-generated code. +// This type is not subject to any compatibility guarantee. +type InternalMessageInfo struct { + marshal *marshalInfo + unmarshal *unmarshalInfo + merge *mergeInfo + discard *discardInfo +} diff --git a/chaincode/abac/go/vendor/github.com/golang/protobuf/proto/message_set.go b/chaincode/abac/go/vendor/github.com/golang/protobuf/proto/message_set.go index fd982dec..3b6ca41d 100644 --- a/chaincode/abac/go/vendor/github.com/golang/protobuf/proto/message_set.go +++ b/chaincode/abac/go/vendor/github.com/golang/protobuf/proto/message_set.go @@ -42,6 +42,7 @@ import ( "fmt" "reflect" "sort" + "sync" ) // errNoMessageTypeID occurs when a protocol buffer does not have a message type ID. @@ -94,10 +95,7 @@ func (ms *messageSet) find(pb Message) *_MessageSet_Item { } func (ms *messageSet) Has(pb Message) bool { - if ms.find(pb) != nil { - return true - } - return false + return ms.find(pb) != nil } func (ms *messageSet) Unmarshal(pb Message) error { @@ -150,46 +148,42 @@ func skipVarint(buf []byte) []byte { // MarshalMessageSet encodes the extension map represented by m in the message set wire format. // It is called by generated Marshal methods on protocol buffer messages with the message_set_wire_format option. func MarshalMessageSet(exts interface{}) ([]byte, error) { - var m map[int32]Extension + return marshalMessageSet(exts, false) +} + +// marshaMessageSet implements above function, with the opt to turn on / off deterministic during Marshal. +func marshalMessageSet(exts interface{}, deterministic bool) ([]byte, error) { switch exts := exts.(type) { case *XXX_InternalExtensions: - if err := encodeExtensions(exts); err != nil { - return nil, err - } - m, _ = exts.extensionsRead() + var u marshalInfo + siz := u.sizeMessageSet(exts) + b := make([]byte, 0, siz) + return u.appendMessageSet(b, exts, deterministic) + case map[int32]Extension: - if err := encodeExtensionsMap(exts); err != nil { - return nil, err + // This is an old-style extension map. + // Wrap it in a new-style XXX_InternalExtensions. + ie := XXX_InternalExtensions{ + p: &struct { + mu sync.Mutex + extensionMap map[int32]Extension + }{ + extensionMap: exts, + }, } - m = exts + + var u marshalInfo + siz := u.sizeMessageSet(&ie) + b := make([]byte, 0, siz) + return u.appendMessageSet(b, &ie, deterministic) + default: return nil, errors.New("proto: not an extension map") } - - // Sort extension IDs to provide a deterministic encoding. - // See also enc_map in encode.go. - ids := make([]int, 0, len(m)) - for id := range m { - ids = append(ids, int(id)) - } - sort.Ints(ids) - - ms := &messageSet{Item: make([]*_MessageSet_Item, 0, len(m))} - for _, id := range ids { - e := m[int32(id)] - // Remove the wire type and field number varint, as well as the length varint. - msg := skipVarint(skipVarint(e.enc)) - - ms.Item = append(ms.Item, &_MessageSet_Item{ - TypeId: Int32(int32(id)), - Message: msg, - }) - } - return Marshal(ms) } // UnmarshalMessageSet decodes the extension map encoded in buf in the message set wire format. -// It is called by generated Unmarshal methods on protocol buffer messages with the message_set_wire_format option. +// It is called by Unmarshal methods on protocol buffer messages with the message_set_wire_format option. func UnmarshalMessageSet(buf []byte, exts interface{}) error { var m map[int32]Extension switch exts := exts.(type) { @@ -235,7 +229,15 @@ func MarshalMessageSetJSON(exts interface{}) ([]byte, error) { var m map[int32]Extension switch exts := exts.(type) { case *XXX_InternalExtensions: - m, _ = exts.extensionsRead() + var mu sync.Locker + m, mu = exts.extensionsRead() + if m != nil { + // Keep the extensions map locked until we're done marshaling to prevent + // races between marshaling and unmarshaling the lazily-{en,de}coded + // values. + mu.Lock() + defer mu.Unlock() + } case map[int32]Extension: m = exts default: @@ -253,15 +255,16 @@ func MarshalMessageSetJSON(exts interface{}) ([]byte, error) { for i, id := range ids { ext := m[id] - if i > 0 { - b.WriteByte(',') - } - msd, ok := messageSetMap[id] if !ok { // Unknown type; we can't render it, so skip it. continue } + + if i > 0 && b.Len() > 1 { + b.WriteByte(',') + } + fmt.Fprintf(&b, `"[%s]":`, msd.name) x := ext.value diff --git a/chaincode/abac/go/vendor/github.com/golang/protobuf/proto/pointer_reflect.go b/chaincode/abac/go/vendor/github.com/golang/protobuf/proto/pointer_reflect.go index fb512e2e..b6cad908 100644 --- a/chaincode/abac/go/vendor/github.com/golang/protobuf/proto/pointer_reflect.go +++ b/chaincode/abac/go/vendor/github.com/golang/protobuf/proto/pointer_reflect.go @@ -29,7 +29,7 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// +build appengine js +// +build purego appengine js // This file contains an implementation of proto field accesses using package reflect. // It is slower than the code in pointer_unsafe.go but it avoids package unsafe and can @@ -38,32 +38,13 @@ package proto import ( - "math" "reflect" + "sync" ) -// A structPointer is a pointer to a struct. -type structPointer struct { - v reflect.Value -} +const unsafeAllowed = false -// toStructPointer returns a structPointer equivalent to the given reflect value. -// The reflect value must itself be a pointer to a struct. -func toStructPointer(v reflect.Value) structPointer { - return structPointer{v} -} - -// IsNil reports whether p is nil. -func structPointer_IsNil(p structPointer) bool { - return p.v.IsNil() -} - -// Interface returns the struct pointer as an interface value. -func structPointer_Interface(p structPointer, _ reflect.Type) interface{} { - return p.v.Interface() -} - -// A field identifies a field in a struct, accessible from a structPointer. +// A field identifies a field in a struct, accessible from a pointer. // In this implementation, a field is identified by the sequence of field indices // passed to reflect's FieldByIndex. type field []int @@ -76,409 +57,301 @@ func toField(f *reflect.StructField) field { // invalidField is an invalid field identifier. var invalidField = field(nil) +// zeroField is a noop when calling pointer.offset. +var zeroField = field([]int{}) + // IsValid reports whether the field identifier is valid. func (f field) IsValid() bool { return f != nil } -// field returns the given field in the struct as a reflect value. -func structPointer_field(p structPointer, f field) reflect.Value { - // Special case: an extension map entry with a value of type T - // passes a *T to the struct-handling code with a zero field, - // expecting that it will be treated as equivalent to *struct{ X T }, - // which has the same memory layout. We have to handle that case - // specially, because reflect will panic if we call FieldByIndex on a - // non-struct. - if f == nil { - return p.v.Elem() - } - - return p.v.Elem().FieldByIndex(f) -} - -// ifield returns the given field in the struct as an interface value. -func structPointer_ifield(p structPointer, f field) interface{} { - return structPointer_field(p, f).Addr().Interface() -} - -// Bytes returns the address of a []byte field in the struct. -func structPointer_Bytes(p structPointer, f field) *[]byte { - return structPointer_ifield(p, f).(*[]byte) -} - -// BytesSlice returns the address of a [][]byte field in the struct. -func structPointer_BytesSlice(p structPointer, f field) *[][]byte { - return structPointer_ifield(p, f).(*[][]byte) -} - -// Bool returns the address of a *bool field in the struct. -func structPointer_Bool(p structPointer, f field) **bool { - return structPointer_ifield(p, f).(**bool) -} - -// BoolVal returns the address of a bool field in the struct. -func structPointer_BoolVal(p structPointer, f field) *bool { - return structPointer_ifield(p, f).(*bool) -} - -// BoolSlice returns the address of a []bool field in the struct. -func structPointer_BoolSlice(p structPointer, f field) *[]bool { - return structPointer_ifield(p, f).(*[]bool) -} - -// String returns the address of a *string field in the struct. -func structPointer_String(p structPointer, f field) **string { - return structPointer_ifield(p, f).(**string) -} - -// StringVal returns the address of a string field in the struct. -func structPointer_StringVal(p structPointer, f field) *string { - return structPointer_ifield(p, f).(*string) -} - -// StringSlice returns the address of a []string field in the struct. -func structPointer_StringSlice(p structPointer, f field) *[]string { - return structPointer_ifield(p, f).(*[]string) -} - -// Extensions returns the address of an extension map field in the struct. -func structPointer_Extensions(p structPointer, f field) *XXX_InternalExtensions { - return structPointer_ifield(p, f).(*XXX_InternalExtensions) -} - -// ExtMap returns the address of an extension map field in the struct. -func structPointer_ExtMap(p structPointer, f field) *map[int32]Extension { - return structPointer_ifield(p, f).(*map[int32]Extension) -} - -// NewAt returns the reflect.Value for a pointer to a field in the struct. -func structPointer_NewAt(p structPointer, f field, typ reflect.Type) reflect.Value { - return structPointer_field(p, f).Addr() -} - -// SetStructPointer writes a *struct field in the struct. -func structPointer_SetStructPointer(p structPointer, f field, q structPointer) { - structPointer_field(p, f).Set(q.v) -} - -// GetStructPointer reads a *struct field in the struct. -func structPointer_GetStructPointer(p structPointer, f field) structPointer { - return structPointer{structPointer_field(p, f)} -} - -// StructPointerSlice the address of a []*struct field in the struct. -func structPointer_StructPointerSlice(p structPointer, f field) structPointerSlice { - return structPointerSlice{structPointer_field(p, f)} -} - -// A structPointerSlice represents the address of a slice of pointers to structs -// (themselves messages or groups). That is, v.Type() is *[]*struct{...}. -type structPointerSlice struct { +// The pointer type is for the table-driven decoder. +// The implementation here uses a reflect.Value of pointer type to +// create a generic pointer. In pointer_unsafe.go we use unsafe +// instead of reflect to implement the same (but faster) interface. +type pointer struct { v reflect.Value } -func (p structPointerSlice) Len() int { return p.v.Len() } -func (p structPointerSlice) Index(i int) structPointer { return structPointer{p.v.Index(i)} } -func (p structPointerSlice) Append(q structPointer) { - p.v.Set(reflect.Append(p.v, q.v)) +// toPointer converts an interface of pointer type to a pointer +// that points to the same target. +func toPointer(i *Message) pointer { + return pointer{v: reflect.ValueOf(*i)} } -var ( - int32Type = reflect.TypeOf(int32(0)) - uint32Type = reflect.TypeOf(uint32(0)) - float32Type = reflect.TypeOf(float32(0)) - int64Type = reflect.TypeOf(int64(0)) - uint64Type = reflect.TypeOf(uint64(0)) - float64Type = reflect.TypeOf(float64(0)) -) - -// A word32 represents a field of type *int32, *uint32, *float32, or *enum. -// That is, v.Type() is *int32, *uint32, *float32, or *enum and v is assignable. -type word32 struct { - v reflect.Value +// toAddrPointer converts an interface to a pointer that points to +// the interface data. +func toAddrPointer(i *interface{}, isptr bool) pointer { + v := reflect.ValueOf(*i) + u := reflect.New(v.Type()) + u.Elem().Set(v) + return pointer{v: u} } -// IsNil reports whether p is nil. -func word32_IsNil(p word32) bool { +// valToPointer converts v to a pointer. v must be of pointer type. +func valToPointer(v reflect.Value) pointer { + return pointer{v: v} +} + +// offset converts from a pointer to a structure to a pointer to +// one of its fields. +func (p pointer) offset(f field) pointer { + return pointer{v: p.v.Elem().FieldByIndex(f).Addr()} +} + +func (p pointer) isNil() bool { return p.v.IsNil() } -// Set sets p to point at a newly allocated word with bits set to x. -func word32_Set(p word32, o *Buffer, x uint32) { - t := p.v.Type().Elem() - switch t { - case int32Type: - if len(o.int32s) == 0 { - o.int32s = make([]int32, uint32PoolSize) - } - o.int32s[0] = int32(x) - p.v.Set(reflect.ValueOf(&o.int32s[0])) - o.int32s = o.int32s[1:] - return - case uint32Type: - if len(o.uint32s) == 0 { - o.uint32s = make([]uint32, uint32PoolSize) - } - o.uint32s[0] = x - p.v.Set(reflect.ValueOf(&o.uint32s[0])) - o.uint32s = o.uint32s[1:] - return - case float32Type: - if len(o.float32s) == 0 { - o.float32s = make([]float32, uint32PoolSize) - } - o.float32s[0] = math.Float32frombits(x) - p.v.Set(reflect.ValueOf(&o.float32s[0])) - o.float32s = o.float32s[1:] - return - } - - // must be enum - p.v.Set(reflect.New(t)) - p.v.Elem().SetInt(int64(int32(x))) -} - -// Get gets the bits pointed at by p, as a uint32. -func word32_Get(p word32) uint32 { - elem := p.v.Elem() - switch elem.Kind() { - case reflect.Int32: - return uint32(elem.Int()) - case reflect.Uint32: - return uint32(elem.Uint()) - case reflect.Float32: - return math.Float32bits(float32(elem.Float())) - } - panic("unreachable") -} - -// Word32 returns a reference to a *int32, *uint32, *float32, or *enum field in the struct. -func structPointer_Word32(p structPointer, f field) word32 { - return word32{structPointer_field(p, f)} -} - -// A word32Val represents a field of type int32, uint32, float32, or enum. -// That is, v.Type() is int32, uint32, float32, or enum and v is assignable. -type word32Val struct { - v reflect.Value -} - -// Set sets *p to x. -func word32Val_Set(p word32Val, x uint32) { - switch p.v.Type() { - case int32Type: - p.v.SetInt(int64(x)) - return - case uint32Type: - p.v.SetUint(uint64(x)) - return - case float32Type: - p.v.SetFloat(float64(math.Float32frombits(x))) - return - } - - // must be enum - p.v.SetInt(int64(int32(x))) -} - -// Get gets the bits pointed at by p, as a uint32. -func word32Val_Get(p word32Val) uint32 { - elem := p.v - switch elem.Kind() { - case reflect.Int32: - return uint32(elem.Int()) - case reflect.Uint32: - return uint32(elem.Uint()) - case reflect.Float32: - return math.Float32bits(float32(elem.Float())) - } - panic("unreachable") -} - -// Word32Val returns a reference to a int32, uint32, float32, or enum field in the struct. -func structPointer_Word32Val(p structPointer, f field) word32Val { - return word32Val{structPointer_field(p, f)} -} - -// A word32Slice is a slice of 32-bit values. -// That is, v.Type() is []int32, []uint32, []float32, or []enum. -type word32Slice struct { - v reflect.Value -} - -func (p word32Slice) Append(x uint32) { - n, m := p.v.Len(), p.v.Cap() +// grow updates the slice s in place to make it one element longer. +// s must be addressable. +// Returns the (addressable) new element. +func grow(s reflect.Value) reflect.Value { + n, m := s.Len(), s.Cap() if n < m { - p.v.SetLen(n + 1) + s.SetLen(n + 1) } else { - t := p.v.Type().Elem() - p.v.Set(reflect.Append(p.v, reflect.Zero(t))) + s.Set(reflect.Append(s, reflect.Zero(s.Type().Elem()))) } - elem := p.v.Index(n) - switch elem.Kind() { - case reflect.Int32: - elem.SetInt(int64(int32(x))) - case reflect.Uint32: - elem.SetUint(uint64(x)) - case reflect.Float32: - elem.SetFloat(float64(math.Float32frombits(x))) + return s.Index(n) +} + +func (p pointer) toInt64() *int64 { + return p.v.Interface().(*int64) +} +func (p pointer) toInt64Ptr() **int64 { + return p.v.Interface().(**int64) +} +func (p pointer) toInt64Slice() *[]int64 { + return p.v.Interface().(*[]int64) +} + +var int32ptr = reflect.TypeOf((*int32)(nil)) + +func (p pointer) toInt32() *int32 { + return p.v.Convert(int32ptr).Interface().(*int32) +} + +// The toInt32Ptr/Slice methods don't work because of enums. +// Instead, we must use set/get methods for the int32ptr/slice case. +/* + func (p pointer) toInt32Ptr() **int32 { + return p.v.Interface().(**int32) +} + func (p pointer) toInt32Slice() *[]int32 { + return p.v.Interface().(*[]int32) +} +*/ +func (p pointer) getInt32Ptr() *int32 { + if p.v.Type().Elem().Elem() == reflect.TypeOf(int32(0)) { + // raw int32 type + return p.v.Elem().Interface().(*int32) } + // an enum + return p.v.Elem().Convert(int32PtrType).Interface().(*int32) +} +func (p pointer) setInt32Ptr(v int32) { + // Allocate value in a *int32. Possibly convert that to a *enum. + // Then assign it to a **int32 or **enum. + // Note: we can convert *int32 to *enum, but we can't convert + // **int32 to **enum! + p.v.Elem().Set(reflect.ValueOf(&v).Convert(p.v.Type().Elem())) } -func (p word32Slice) Len() int { - return p.v.Len() -} - -func (p word32Slice) Index(i int) uint32 { - elem := p.v.Index(i) - switch elem.Kind() { - case reflect.Int32: - return uint32(elem.Int()) - case reflect.Uint32: - return uint32(elem.Uint()) - case reflect.Float32: - return math.Float32bits(float32(elem.Float())) +// getInt32Slice copies []int32 from p as a new slice. +// This behavior differs from the implementation in pointer_unsafe.go. +func (p pointer) getInt32Slice() []int32 { + if p.v.Type().Elem().Elem() == reflect.TypeOf(int32(0)) { + // raw int32 type + return p.v.Elem().Interface().([]int32) } - panic("unreachable") + // an enum + // Allocate a []int32, then assign []enum's values into it. + // Note: we can't convert []enum to []int32. + slice := p.v.Elem() + s := make([]int32, slice.Len()) + for i := 0; i < slice.Len(); i++ { + s[i] = int32(slice.Index(i).Int()) + } + return s } -// Word32Slice returns a reference to a []int32, []uint32, []float32, or []enum field in the struct. -func structPointer_Word32Slice(p structPointer, f field) word32Slice { - return word32Slice{structPointer_field(p, f)} -} - -// word64 is like word32 but for 64-bit values. -type word64 struct { - v reflect.Value -} - -func word64_Set(p word64, o *Buffer, x uint64) { - t := p.v.Type().Elem() - switch t { - case int64Type: - if len(o.int64s) == 0 { - o.int64s = make([]int64, uint64PoolSize) - } - o.int64s[0] = int64(x) - p.v.Set(reflect.ValueOf(&o.int64s[0])) - o.int64s = o.int64s[1:] - return - case uint64Type: - if len(o.uint64s) == 0 { - o.uint64s = make([]uint64, uint64PoolSize) - } - o.uint64s[0] = x - p.v.Set(reflect.ValueOf(&o.uint64s[0])) - o.uint64s = o.uint64s[1:] - return - case float64Type: - if len(o.float64s) == 0 { - o.float64s = make([]float64, uint64PoolSize) - } - o.float64s[0] = math.Float64frombits(x) - p.v.Set(reflect.ValueOf(&o.float64s[0])) - o.float64s = o.float64s[1:] +// setInt32Slice copies []int32 into p as a new slice. +// This behavior differs from the implementation in pointer_unsafe.go. +func (p pointer) setInt32Slice(v []int32) { + if p.v.Type().Elem().Elem() == reflect.TypeOf(int32(0)) { + // raw int32 type + p.v.Elem().Set(reflect.ValueOf(v)) return } - panic("unreachable") -} - -func word64_IsNil(p word64) bool { - return p.v.IsNil() -} - -func word64_Get(p word64) uint64 { - elem := p.v.Elem() - switch elem.Kind() { - case reflect.Int64: - return uint64(elem.Int()) - case reflect.Uint64: - return elem.Uint() - case reflect.Float64: - return math.Float64bits(elem.Float()) + // an enum + // Allocate a []enum, then assign []int32's values into it. + // Note: we can't convert []enum to []int32. + slice := reflect.MakeSlice(p.v.Type().Elem(), len(v), cap(v)) + for i, x := range v { + slice.Index(i).SetInt(int64(x)) } - panic("unreachable") + p.v.Elem().Set(slice) +} +func (p pointer) appendInt32Slice(v int32) { + grow(p.v.Elem()).SetInt(int64(v)) } -func structPointer_Word64(p structPointer, f field) word64 { - return word64{structPointer_field(p, f)} +func (p pointer) toUint64() *uint64 { + return p.v.Interface().(*uint64) +} +func (p pointer) toUint64Ptr() **uint64 { + return p.v.Interface().(**uint64) +} +func (p pointer) toUint64Slice() *[]uint64 { + return p.v.Interface().(*[]uint64) +} +func (p pointer) toUint32() *uint32 { + return p.v.Interface().(*uint32) +} +func (p pointer) toUint32Ptr() **uint32 { + return p.v.Interface().(**uint32) +} +func (p pointer) toUint32Slice() *[]uint32 { + return p.v.Interface().(*[]uint32) +} +func (p pointer) toBool() *bool { + return p.v.Interface().(*bool) +} +func (p pointer) toBoolPtr() **bool { + return p.v.Interface().(**bool) +} +func (p pointer) toBoolSlice() *[]bool { + return p.v.Interface().(*[]bool) +} +func (p pointer) toFloat64() *float64 { + return p.v.Interface().(*float64) +} +func (p pointer) toFloat64Ptr() **float64 { + return p.v.Interface().(**float64) +} +func (p pointer) toFloat64Slice() *[]float64 { + return p.v.Interface().(*[]float64) +} +func (p pointer) toFloat32() *float32 { + return p.v.Interface().(*float32) +} +func (p pointer) toFloat32Ptr() **float32 { + return p.v.Interface().(**float32) +} +func (p pointer) toFloat32Slice() *[]float32 { + return p.v.Interface().(*[]float32) +} +func (p pointer) toString() *string { + return p.v.Interface().(*string) +} +func (p pointer) toStringPtr() **string { + return p.v.Interface().(**string) +} +func (p pointer) toStringSlice() *[]string { + return p.v.Interface().(*[]string) +} +func (p pointer) toBytes() *[]byte { + return p.v.Interface().(*[]byte) +} +func (p pointer) toBytesSlice() *[][]byte { + return p.v.Interface().(*[][]byte) +} +func (p pointer) toExtensions() *XXX_InternalExtensions { + return p.v.Interface().(*XXX_InternalExtensions) +} +func (p pointer) toOldExtensions() *map[int32]Extension { + return p.v.Interface().(*map[int32]Extension) +} +func (p pointer) getPointer() pointer { + return pointer{v: p.v.Elem()} +} +func (p pointer) setPointer(q pointer) { + p.v.Elem().Set(q.v) +} +func (p pointer) appendPointer(q pointer) { + grow(p.v.Elem()).Set(q.v) } -// word64Val is like word32Val but for 64-bit values. -type word64Val struct { - v reflect.Value +// getPointerSlice copies []*T from p as a new []pointer. +// This behavior differs from the implementation in pointer_unsafe.go. +func (p pointer) getPointerSlice() []pointer { + if p.v.IsNil() { + return nil + } + n := p.v.Elem().Len() + s := make([]pointer, n) + for i := 0; i < n; i++ { + s[i] = pointer{v: p.v.Elem().Index(i)} + } + return s } -func word64Val_Set(p word64Val, o *Buffer, x uint64) { - switch p.v.Type() { - case int64Type: - p.v.SetInt(int64(x)) - return - case uint64Type: - p.v.SetUint(x) - return - case float64Type: - p.v.SetFloat(math.Float64frombits(x)) +// setPointerSlice copies []pointer into p as a new []*T. +// This behavior differs from the implementation in pointer_unsafe.go. +func (p pointer) setPointerSlice(v []pointer) { + if v == nil { + p.v.Elem().Set(reflect.New(p.v.Elem().Type()).Elem()) return } - panic("unreachable") -} - -func word64Val_Get(p word64Val) uint64 { - elem := p.v - switch elem.Kind() { - case reflect.Int64: - return uint64(elem.Int()) - case reflect.Uint64: - return elem.Uint() - case reflect.Float64: - return math.Float64bits(elem.Float()) + s := reflect.MakeSlice(p.v.Elem().Type(), 0, len(v)) + for _, p := range v { + s = reflect.Append(s, p.v) } - panic("unreachable") + p.v.Elem().Set(s) } -func structPointer_Word64Val(p structPointer, f field) word64Val { - return word64Val{structPointer_field(p, f)} -} - -type word64Slice struct { - v reflect.Value -} - -func (p word64Slice) Append(x uint64) { - n, m := p.v.Len(), p.v.Cap() - if n < m { - p.v.SetLen(n + 1) - } else { - t := p.v.Type().Elem() - p.v.Set(reflect.Append(p.v, reflect.Zero(t))) - } - elem := p.v.Index(n) - switch elem.Kind() { - case reflect.Int64: - elem.SetInt(int64(int64(x))) - case reflect.Uint64: - elem.SetUint(uint64(x)) - case reflect.Float64: - elem.SetFloat(float64(math.Float64frombits(x))) +// getInterfacePointer returns a pointer that points to the +// interface data of the interface pointed by p. +func (p pointer) getInterfacePointer() pointer { + if p.v.Elem().IsNil() { + return pointer{v: p.v.Elem()} } + return pointer{v: p.v.Elem().Elem().Elem().Field(0).Addr()} // *interface -> interface -> *struct -> struct } -func (p word64Slice) Len() int { - return p.v.Len() +func (p pointer) asPointerTo(t reflect.Type) reflect.Value { + // TODO: check that p.v.Type().Elem() == t? + return p.v } -func (p word64Slice) Index(i int) uint64 { - elem := p.v.Index(i) - switch elem.Kind() { - case reflect.Int64: - return uint64(elem.Int()) - case reflect.Uint64: - return uint64(elem.Uint()) - case reflect.Float64: - return math.Float64bits(float64(elem.Float())) - } - panic("unreachable") +func atomicLoadUnmarshalInfo(p **unmarshalInfo) *unmarshalInfo { + atomicLock.Lock() + defer atomicLock.Unlock() + return *p +} +func atomicStoreUnmarshalInfo(p **unmarshalInfo, v *unmarshalInfo) { + atomicLock.Lock() + defer atomicLock.Unlock() + *p = v +} +func atomicLoadMarshalInfo(p **marshalInfo) *marshalInfo { + atomicLock.Lock() + defer atomicLock.Unlock() + return *p +} +func atomicStoreMarshalInfo(p **marshalInfo, v *marshalInfo) { + atomicLock.Lock() + defer atomicLock.Unlock() + *p = v +} +func atomicLoadMergeInfo(p **mergeInfo) *mergeInfo { + atomicLock.Lock() + defer atomicLock.Unlock() + return *p +} +func atomicStoreMergeInfo(p **mergeInfo, v *mergeInfo) { + atomicLock.Lock() + defer atomicLock.Unlock() + *p = v +} +func atomicLoadDiscardInfo(p **discardInfo) *discardInfo { + atomicLock.Lock() + defer atomicLock.Unlock() + return *p +} +func atomicStoreDiscardInfo(p **discardInfo, v *discardInfo) { + atomicLock.Lock() + defer atomicLock.Unlock() + *p = v } -func structPointer_Word64Slice(p structPointer, f field) word64Slice { - return word64Slice{structPointer_field(p, f)} -} +var atomicLock sync.Mutex diff --git a/chaincode/abac/go/vendor/github.com/golang/protobuf/proto/pointer_unsafe.go b/chaincode/abac/go/vendor/github.com/golang/protobuf/proto/pointer_unsafe.go index 6b5567d4..d55a335d 100644 --- a/chaincode/abac/go/vendor/github.com/golang/protobuf/proto/pointer_unsafe.go +++ b/chaincode/abac/go/vendor/github.com/golang/protobuf/proto/pointer_unsafe.go @@ -29,7 +29,7 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// +build !appengine,!js +// +build !purego,!appengine,!js // This file contains the implementation of the proto field accesses using package unsafe. @@ -37,38 +37,13 @@ package proto import ( "reflect" + "sync/atomic" "unsafe" ) -// NOTE: These type_Foo functions would more idiomatically be methods, -// but Go does not allow methods on pointer types, and we must preserve -// some pointer type for the garbage collector. We use these -// funcs with clunky names as our poor approximation to methods. -// -// An alternative would be -// type structPointer struct { p unsafe.Pointer } -// but that does not registerize as well. +const unsafeAllowed = true -// A structPointer is a pointer to a struct. -type structPointer unsafe.Pointer - -// toStructPointer returns a structPointer equivalent to the given reflect value. -func toStructPointer(v reflect.Value) structPointer { - return structPointer(unsafe.Pointer(v.Pointer())) -} - -// IsNil reports whether p is nil. -func structPointer_IsNil(p structPointer) bool { - return p == nil -} - -// Interface returns the struct pointer, assumed to have element type t, -// as an interface value. -func structPointer_Interface(p structPointer, t reflect.Type) interface{} { - return reflect.NewAt(t, unsafe.Pointer(p)).Interface() -} - -// A field identifies a field in a struct, accessible from a structPointer. +// A field identifies a field in a struct, accessible from a pointer. // In this implementation, a field is identified by its byte offset from the start of the struct. type field uintptr @@ -80,191 +55,254 @@ func toField(f *reflect.StructField) field { // invalidField is an invalid field identifier. const invalidField = ^field(0) +// zeroField is a noop when calling pointer.offset. +const zeroField = field(0) + // IsValid reports whether the field identifier is valid. func (f field) IsValid() bool { - return f != ^field(0) + return f != invalidField } -// Bytes returns the address of a []byte field in the struct. -func structPointer_Bytes(p structPointer, f field) *[]byte { - return (*[]byte)(unsafe.Pointer(uintptr(p) + uintptr(f))) +// The pointer type below is for the new table-driven encoder/decoder. +// The implementation here uses unsafe.Pointer to create a generic pointer. +// In pointer_reflect.go we use reflect instead of unsafe to implement +// the same (but slower) interface. +type pointer struct { + p unsafe.Pointer } -// BytesSlice returns the address of a [][]byte field in the struct. -func structPointer_BytesSlice(p structPointer, f field) *[][]byte { - return (*[][]byte)(unsafe.Pointer(uintptr(p) + uintptr(f))) +// size of pointer +var ptrSize = unsafe.Sizeof(uintptr(0)) + +// toPointer converts an interface of pointer type to a pointer +// that points to the same target. +func toPointer(i *Message) pointer { + // Super-tricky - read pointer out of data word of interface value. + // Saves ~25ns over the equivalent: + // return valToPointer(reflect.ValueOf(*i)) + return pointer{p: (*[2]unsafe.Pointer)(unsafe.Pointer(i))[1]} } -// Bool returns the address of a *bool field in the struct. -func structPointer_Bool(p structPointer, f field) **bool { - return (**bool)(unsafe.Pointer(uintptr(p) + uintptr(f))) -} - -// BoolVal returns the address of a bool field in the struct. -func structPointer_BoolVal(p structPointer, f field) *bool { - return (*bool)(unsafe.Pointer(uintptr(p) + uintptr(f))) -} - -// BoolSlice returns the address of a []bool field in the struct. -func structPointer_BoolSlice(p structPointer, f field) *[]bool { - return (*[]bool)(unsafe.Pointer(uintptr(p) + uintptr(f))) -} - -// String returns the address of a *string field in the struct. -func structPointer_String(p structPointer, f field) **string { - return (**string)(unsafe.Pointer(uintptr(p) + uintptr(f))) -} - -// StringVal returns the address of a string field in the struct. -func structPointer_StringVal(p structPointer, f field) *string { - return (*string)(unsafe.Pointer(uintptr(p) + uintptr(f))) -} - -// StringSlice returns the address of a []string field in the struct. -func structPointer_StringSlice(p structPointer, f field) *[]string { - return (*[]string)(unsafe.Pointer(uintptr(p) + uintptr(f))) -} - -// ExtMap returns the address of an extension map field in the struct. -func structPointer_Extensions(p structPointer, f field) *XXX_InternalExtensions { - return (*XXX_InternalExtensions)(unsafe.Pointer(uintptr(p) + uintptr(f))) -} - -func structPointer_ExtMap(p structPointer, f field) *map[int32]Extension { - return (*map[int32]Extension)(unsafe.Pointer(uintptr(p) + uintptr(f))) -} - -// NewAt returns the reflect.Value for a pointer to a field in the struct. -func structPointer_NewAt(p structPointer, f field, typ reflect.Type) reflect.Value { - return reflect.NewAt(typ, unsafe.Pointer(uintptr(p)+uintptr(f))) -} - -// SetStructPointer writes a *struct field in the struct. -func structPointer_SetStructPointer(p structPointer, f field, q structPointer) { - *(*structPointer)(unsafe.Pointer(uintptr(p) + uintptr(f))) = q -} - -// GetStructPointer reads a *struct field in the struct. -func structPointer_GetStructPointer(p structPointer, f field) structPointer { - return *(*structPointer)(unsafe.Pointer(uintptr(p) + uintptr(f))) -} - -// StructPointerSlice the address of a []*struct field in the struct. -func structPointer_StructPointerSlice(p structPointer, f field) *structPointerSlice { - return (*structPointerSlice)(unsafe.Pointer(uintptr(p) + uintptr(f))) -} - -// A structPointerSlice represents a slice of pointers to structs (themselves submessages or groups). -type structPointerSlice []structPointer - -func (v *structPointerSlice) Len() int { return len(*v) } -func (v *structPointerSlice) Index(i int) structPointer { return (*v)[i] } -func (v *structPointerSlice) Append(p structPointer) { *v = append(*v, p) } - -// A word32 is the address of a "pointer to 32-bit value" field. -type word32 **uint32 - -// IsNil reports whether *v is nil. -func word32_IsNil(p word32) bool { - return *p == nil -} - -// Set sets *v to point at a newly allocated word set to x. -func word32_Set(p word32, o *Buffer, x uint32) { - if len(o.uint32s) == 0 { - o.uint32s = make([]uint32, uint32PoolSize) +// toAddrPointer converts an interface to a pointer that points to +// the interface data. +func toAddrPointer(i *interface{}, isptr bool) pointer { + // Super-tricky - read or get the address of data word of interface value. + if isptr { + // The interface is of pointer type, thus it is a direct interface. + // The data word is the pointer data itself. We take its address. + return pointer{p: unsafe.Pointer(uintptr(unsafe.Pointer(i)) + ptrSize)} } - o.uint32s[0] = x - *p = &o.uint32s[0] - o.uint32s = o.uint32s[1:] + // The interface is not of pointer type. The data word is the pointer + // to the data. + return pointer{p: (*[2]unsafe.Pointer)(unsafe.Pointer(i))[1]} } -// Get gets the value pointed at by *v. -func word32_Get(p word32) uint32 { - return **p +// valToPointer converts v to a pointer. v must be of pointer type. +func valToPointer(v reflect.Value) pointer { + return pointer{p: unsafe.Pointer(v.Pointer())} } -// Word32 returns the address of a *int32, *uint32, *float32, or *enum field in the struct. -func structPointer_Word32(p structPointer, f field) word32 { - return word32((**uint32)(unsafe.Pointer(uintptr(p) + uintptr(f)))) +// offset converts from a pointer to a structure to a pointer to +// one of its fields. +func (p pointer) offset(f field) pointer { + // For safety, we should panic if !f.IsValid, however calling panic causes + // this to no longer be inlineable, which is a serious performance cost. + /* + if !f.IsValid() { + panic("invalid field") + } + */ + return pointer{p: unsafe.Pointer(uintptr(p.p) + uintptr(f))} } -// A word32Val is the address of a 32-bit value field. -type word32Val *uint32 - -// Set sets *p to x. -func word32Val_Set(p word32Val, x uint32) { - *p = x +func (p pointer) isNil() bool { + return p.p == nil } -// Get gets the value pointed at by p. -func word32Val_Get(p word32Val) uint32 { - return *p +func (p pointer) toInt64() *int64 { + return (*int64)(p.p) +} +func (p pointer) toInt64Ptr() **int64 { + return (**int64)(p.p) +} +func (p pointer) toInt64Slice() *[]int64 { + return (*[]int64)(p.p) +} +func (p pointer) toInt32() *int32 { + return (*int32)(p.p) } -// Word32Val returns the address of a *int32, *uint32, *float32, or *enum field in the struct. -func structPointer_Word32Val(p structPointer, f field) word32Val { - return word32Val((*uint32)(unsafe.Pointer(uintptr(p) + uintptr(f)))) -} - -// A word32Slice is a slice of 32-bit values. -type word32Slice []uint32 - -func (v *word32Slice) Append(x uint32) { *v = append(*v, x) } -func (v *word32Slice) Len() int { return len(*v) } -func (v *word32Slice) Index(i int) uint32 { return (*v)[i] } - -// Word32Slice returns the address of a []int32, []uint32, []float32, or []enum field in the struct. -func structPointer_Word32Slice(p structPointer, f field) *word32Slice { - return (*word32Slice)(unsafe.Pointer(uintptr(p) + uintptr(f))) -} - -// word64 is like word32 but for 64-bit values. -type word64 **uint64 - -func word64_Set(p word64, o *Buffer, x uint64) { - if len(o.uint64s) == 0 { - o.uint64s = make([]uint64, uint64PoolSize) +// See pointer_reflect.go for why toInt32Ptr/Slice doesn't exist. +/* + func (p pointer) toInt32Ptr() **int32 { + return (**int32)(p.p) } - o.uint64s[0] = x - *p = &o.uint64s[0] - o.uint64s = o.uint64s[1:] + func (p pointer) toInt32Slice() *[]int32 { + return (*[]int32)(p.p) + } +*/ +func (p pointer) getInt32Ptr() *int32 { + return *(**int32)(p.p) +} +func (p pointer) setInt32Ptr(v int32) { + *(**int32)(p.p) = &v } -func word64_IsNil(p word64) bool { - return *p == nil +// getInt32Slice loads a []int32 from p. +// The value returned is aliased with the original slice. +// This behavior differs from the implementation in pointer_reflect.go. +func (p pointer) getInt32Slice() []int32 { + return *(*[]int32)(p.p) } -func word64_Get(p word64) uint64 { - return **p +// setInt32Slice stores a []int32 to p. +// The value set is aliased with the input slice. +// This behavior differs from the implementation in pointer_reflect.go. +func (p pointer) setInt32Slice(v []int32) { + *(*[]int32)(p.p) = v } -func structPointer_Word64(p structPointer, f field) word64 { - return word64((**uint64)(unsafe.Pointer(uintptr(p) + uintptr(f)))) +// TODO: Can we get rid of appendInt32Slice and use setInt32Slice instead? +func (p pointer) appendInt32Slice(v int32) { + s := (*[]int32)(p.p) + *s = append(*s, v) } -// word64Val is like word32Val but for 64-bit values. -type word64Val *uint64 - -func word64Val_Set(p word64Val, o *Buffer, x uint64) { - *p = x +func (p pointer) toUint64() *uint64 { + return (*uint64)(p.p) +} +func (p pointer) toUint64Ptr() **uint64 { + return (**uint64)(p.p) +} +func (p pointer) toUint64Slice() *[]uint64 { + return (*[]uint64)(p.p) +} +func (p pointer) toUint32() *uint32 { + return (*uint32)(p.p) +} +func (p pointer) toUint32Ptr() **uint32 { + return (**uint32)(p.p) +} +func (p pointer) toUint32Slice() *[]uint32 { + return (*[]uint32)(p.p) +} +func (p pointer) toBool() *bool { + return (*bool)(p.p) +} +func (p pointer) toBoolPtr() **bool { + return (**bool)(p.p) +} +func (p pointer) toBoolSlice() *[]bool { + return (*[]bool)(p.p) +} +func (p pointer) toFloat64() *float64 { + return (*float64)(p.p) +} +func (p pointer) toFloat64Ptr() **float64 { + return (**float64)(p.p) +} +func (p pointer) toFloat64Slice() *[]float64 { + return (*[]float64)(p.p) +} +func (p pointer) toFloat32() *float32 { + return (*float32)(p.p) +} +func (p pointer) toFloat32Ptr() **float32 { + return (**float32)(p.p) +} +func (p pointer) toFloat32Slice() *[]float32 { + return (*[]float32)(p.p) +} +func (p pointer) toString() *string { + return (*string)(p.p) +} +func (p pointer) toStringPtr() **string { + return (**string)(p.p) +} +func (p pointer) toStringSlice() *[]string { + return (*[]string)(p.p) +} +func (p pointer) toBytes() *[]byte { + return (*[]byte)(p.p) +} +func (p pointer) toBytesSlice() *[][]byte { + return (*[][]byte)(p.p) +} +func (p pointer) toExtensions() *XXX_InternalExtensions { + return (*XXX_InternalExtensions)(p.p) +} +func (p pointer) toOldExtensions() *map[int32]Extension { + return (*map[int32]Extension)(p.p) } -func word64Val_Get(p word64Val) uint64 { - return *p +// getPointerSlice loads []*T from p as a []pointer. +// The value returned is aliased with the original slice. +// This behavior differs from the implementation in pointer_reflect.go. +func (p pointer) getPointerSlice() []pointer { + // Super-tricky - p should point to a []*T where T is a + // message type. We load it as []pointer. + return *(*[]pointer)(p.p) } -func structPointer_Word64Val(p structPointer, f field) word64Val { - return word64Val((*uint64)(unsafe.Pointer(uintptr(p) + uintptr(f)))) +// setPointerSlice stores []pointer into p as a []*T. +// The value set is aliased with the input slice. +// This behavior differs from the implementation in pointer_reflect.go. +func (p pointer) setPointerSlice(v []pointer) { + // Super-tricky - p should point to a []*T where T is a + // message type. We store it as []pointer. + *(*[]pointer)(p.p) = v } -// word64Slice is like word32Slice but for 64-bit values. -type word64Slice []uint64 - -func (v *word64Slice) Append(x uint64) { *v = append(*v, x) } -func (v *word64Slice) Len() int { return len(*v) } -func (v *word64Slice) Index(i int) uint64 { return (*v)[i] } - -func structPointer_Word64Slice(p structPointer, f field) *word64Slice { - return (*word64Slice)(unsafe.Pointer(uintptr(p) + uintptr(f))) +// getPointer loads the pointer at p and returns it. +func (p pointer) getPointer() pointer { + return pointer{p: *(*unsafe.Pointer)(p.p)} +} + +// setPointer stores the pointer q at p. +func (p pointer) setPointer(q pointer) { + *(*unsafe.Pointer)(p.p) = q.p +} + +// append q to the slice pointed to by p. +func (p pointer) appendPointer(q pointer) { + s := (*[]unsafe.Pointer)(p.p) + *s = append(*s, q.p) +} + +// getInterfacePointer returns a pointer that points to the +// interface data of the interface pointed by p. +func (p pointer) getInterfacePointer() pointer { + // Super-tricky - read pointer out of data word of interface value. + return pointer{p: (*(*[2]unsafe.Pointer)(p.p))[1]} +} + +// asPointerTo returns a reflect.Value that is a pointer to an +// object of type t stored at p. +func (p pointer) asPointerTo(t reflect.Type) reflect.Value { + return reflect.NewAt(t, p.p) +} + +func atomicLoadUnmarshalInfo(p **unmarshalInfo) *unmarshalInfo { + return (*unmarshalInfo)(atomic.LoadPointer((*unsafe.Pointer)(unsafe.Pointer(p)))) +} +func atomicStoreUnmarshalInfo(p **unmarshalInfo, v *unmarshalInfo) { + atomic.StorePointer((*unsafe.Pointer)(unsafe.Pointer(p)), unsafe.Pointer(v)) +} +func atomicLoadMarshalInfo(p **marshalInfo) *marshalInfo { + return (*marshalInfo)(atomic.LoadPointer((*unsafe.Pointer)(unsafe.Pointer(p)))) +} +func atomicStoreMarshalInfo(p **marshalInfo, v *marshalInfo) { + atomic.StorePointer((*unsafe.Pointer)(unsafe.Pointer(p)), unsafe.Pointer(v)) +} +func atomicLoadMergeInfo(p **mergeInfo) *mergeInfo { + return (*mergeInfo)(atomic.LoadPointer((*unsafe.Pointer)(unsafe.Pointer(p)))) +} +func atomicStoreMergeInfo(p **mergeInfo, v *mergeInfo) { + atomic.StorePointer((*unsafe.Pointer)(unsafe.Pointer(p)), unsafe.Pointer(v)) +} +func atomicLoadDiscardInfo(p **discardInfo) *discardInfo { + return (*discardInfo)(atomic.LoadPointer((*unsafe.Pointer)(unsafe.Pointer(p)))) +} +func atomicStoreDiscardInfo(p **discardInfo, v *discardInfo) { + atomic.StorePointer((*unsafe.Pointer)(unsafe.Pointer(p)), unsafe.Pointer(v)) } diff --git a/chaincode/abac/go/vendor/github.com/golang/protobuf/proto/properties.go b/chaincode/abac/go/vendor/github.com/golang/protobuf/proto/properties.go index ec2289c0..dce098e6 100644 --- a/chaincode/abac/go/vendor/github.com/golang/protobuf/proto/properties.go +++ b/chaincode/abac/go/vendor/github.com/golang/protobuf/proto/properties.go @@ -58,42 +58,6 @@ const ( WireFixed32 = 5 ) -const startSize = 10 // initial slice/string sizes - -// Encoders are defined in encode.go -// An encoder outputs the full representation of a field, including its -// tag and encoder type. -type encoder func(p *Buffer, prop *Properties, base structPointer) error - -// A valueEncoder encodes a single integer in a particular encoding. -type valueEncoder func(o *Buffer, x uint64) error - -// Sizers are defined in encode.go -// A sizer returns the encoded size of a field, including its tag and encoder -// type. -type sizer func(prop *Properties, base structPointer) int - -// A valueSizer returns the encoded size of a single integer in a particular -// encoding. -type valueSizer func(x uint64) int - -// Decoders are defined in decode.go -// A decoder creates a value from its wire representation. -// Unrecognized subelements are saved in unrec. -type decoder func(p *Buffer, prop *Properties, base structPointer) error - -// A valueDecoder decodes a single integer in a particular encoding. -type valueDecoder func(o *Buffer) (x uint64, err error) - -// A oneofMarshaler does the marshaling for all oneof fields in a message. -type oneofMarshaler func(Message, *Buffer) error - -// A oneofUnmarshaler does the unmarshaling for a oneof field in a message. -type oneofUnmarshaler func(Message, int, int, *Buffer) (bool, error) - -// A oneofSizer does the sizing for all oneof fields in a message. -type oneofSizer func(Message) int - // tagMap is an optimization over map[int]int for typical protocol buffer // use-cases. Encoded protocol buffers are often in tag order with small tag // numbers. @@ -140,13 +104,6 @@ type StructProperties struct { decoderTags tagMap // map from proto tag to struct field number decoderOrigNames map[string]int // map from original name to struct field number order []int // list of struct field numbers in tag order - unrecField field // field id of the XXX_unrecognized []byte field - extendable bool // is this an extendable proto - - oneofMarshaler oneofMarshaler - oneofUnmarshaler oneofUnmarshaler - oneofSizer oneofSizer - stype reflect.Type // OneofTypes contains information about the oneof fields in this message. // It is keyed by the original name of a field. @@ -182,41 +139,24 @@ type Properties struct { Repeated bool Packed bool // relevant for repeated primitives only Enum string // set for enum types only - proto3 bool // whether this is known to be a proto3 field; set for []byte only + proto3 bool // whether this is known to be a proto3 field oneof bool // whether this is a oneof field Default string // default value HasDefault bool // whether an explicit default was provided - def_uint64 uint64 - enc encoder - valEnc valueEncoder // set for bool and numeric types only - field field - tagcode []byte // encoding of EncodeVarint((Tag<<3)|WireType) - tagbuf [8]byte - stype reflect.Type // set for struct types only - sprop *StructProperties // set for struct types only - isMarshaler bool - isUnmarshaler bool + stype reflect.Type // set for struct types only + sprop *StructProperties // set for struct types only - mtype reflect.Type // set for map types only - mkeyprop *Properties // set for map types only - mvalprop *Properties // set for map types only - - size sizer - valSize valueSizer // set for bool and numeric types only - - dec decoder - valDec valueDecoder // set for bool and numeric types only - - // If this is a packable field, this will be the decoder for the packed version of the field. - packedDec decoder + mtype reflect.Type // set for map types only + MapKeyProp *Properties // set for map types only + MapValProp *Properties // set for map types only } // String formats the properties in the protobuf struct field tag style. func (p *Properties) String() string { s := p.Wire - s = "," + s += "," s += strconv.Itoa(p.Tag) if p.Required { s += ",req" @@ -262,29 +202,14 @@ func (p *Properties) Parse(s string) { switch p.Wire { case "varint": p.WireType = WireVarint - p.valEnc = (*Buffer).EncodeVarint - p.valDec = (*Buffer).DecodeVarint - p.valSize = sizeVarint case "fixed32": p.WireType = WireFixed32 - p.valEnc = (*Buffer).EncodeFixed32 - p.valDec = (*Buffer).DecodeFixed32 - p.valSize = sizeFixed32 case "fixed64": p.WireType = WireFixed64 - p.valEnc = (*Buffer).EncodeFixed64 - p.valDec = (*Buffer).DecodeFixed64 - p.valSize = sizeFixed64 case "zigzag32": p.WireType = WireVarint - p.valEnc = (*Buffer).EncodeZigzag32 - p.valDec = (*Buffer).DecodeZigzag32 - p.valSize = sizeZigzag32 case "zigzag64": p.WireType = WireVarint - p.valEnc = (*Buffer).EncodeZigzag64 - p.valDec = (*Buffer).DecodeZigzag64 - p.valSize = sizeZigzag64 case "bytes", "group": p.WireType = WireBytes // no numeric converter for non-numeric types @@ -299,6 +224,7 @@ func (p *Properties) Parse(s string) { return } +outer: for i := 2; i < len(fields); i++ { f := fields[i] switch { @@ -326,256 +252,41 @@ func (p *Properties) Parse(s string) { if i+1 < len(fields) { // Commas aren't escaped, and def is always last. p.Default += "," + strings.Join(fields[i+1:], ",") - break + break outer } } } } -func logNoSliceEnc(t1, t2 reflect.Type) { - fmt.Fprintf(os.Stderr, "proto: no slice oenc for %T = []%T\n", t1, t2) -} - var protoMessageType = reflect.TypeOf((*Message)(nil)).Elem() -// Initialize the fields for encoding and decoding. -func (p *Properties) setEncAndDec(typ reflect.Type, f *reflect.StructField, lockGetProp bool) { - p.enc = nil - p.dec = nil - p.size = nil - +// setFieldProps initializes the field properties for submessages and maps. +func (p *Properties) setFieldProps(typ reflect.Type, f *reflect.StructField, lockGetProp bool) { switch t1 := typ; t1.Kind() { - default: - fmt.Fprintf(os.Stderr, "proto: no coders for %v\n", t1) - - // proto3 scalar types - - case reflect.Bool: - p.enc = (*Buffer).enc_proto3_bool - p.dec = (*Buffer).dec_proto3_bool - p.size = size_proto3_bool - case reflect.Int32: - p.enc = (*Buffer).enc_proto3_int32 - p.dec = (*Buffer).dec_proto3_int32 - p.size = size_proto3_int32 - case reflect.Uint32: - p.enc = (*Buffer).enc_proto3_uint32 - p.dec = (*Buffer).dec_proto3_int32 // can reuse - p.size = size_proto3_uint32 - case reflect.Int64, reflect.Uint64: - p.enc = (*Buffer).enc_proto3_int64 - p.dec = (*Buffer).dec_proto3_int64 - p.size = size_proto3_int64 - case reflect.Float32: - p.enc = (*Buffer).enc_proto3_uint32 // can just treat them as bits - p.dec = (*Buffer).dec_proto3_int32 - p.size = size_proto3_uint32 - case reflect.Float64: - p.enc = (*Buffer).enc_proto3_int64 // can just treat them as bits - p.dec = (*Buffer).dec_proto3_int64 - p.size = size_proto3_int64 - case reflect.String: - p.enc = (*Buffer).enc_proto3_string - p.dec = (*Buffer).dec_proto3_string - p.size = size_proto3_string - case reflect.Ptr: - switch t2 := t1.Elem(); t2.Kind() { - default: - fmt.Fprintf(os.Stderr, "proto: no encoder function for %v -> %v\n", t1, t2) - break - case reflect.Bool: - p.enc = (*Buffer).enc_bool - p.dec = (*Buffer).dec_bool - p.size = size_bool - case reflect.Int32: - p.enc = (*Buffer).enc_int32 - p.dec = (*Buffer).dec_int32 - p.size = size_int32 - case reflect.Uint32: - p.enc = (*Buffer).enc_uint32 - p.dec = (*Buffer).dec_int32 // can reuse - p.size = size_uint32 - case reflect.Int64, reflect.Uint64: - p.enc = (*Buffer).enc_int64 - p.dec = (*Buffer).dec_int64 - p.size = size_int64 - case reflect.Float32: - p.enc = (*Buffer).enc_uint32 // can just treat them as bits - p.dec = (*Buffer).dec_int32 - p.size = size_uint32 - case reflect.Float64: - p.enc = (*Buffer).enc_int64 // can just treat them as bits - p.dec = (*Buffer).dec_int64 - p.size = size_int64 - case reflect.String: - p.enc = (*Buffer).enc_string - p.dec = (*Buffer).dec_string - p.size = size_string - case reflect.Struct: + if t1.Elem().Kind() == reflect.Struct { p.stype = t1.Elem() - p.isMarshaler = isMarshaler(t1) - p.isUnmarshaler = isUnmarshaler(t1) - if p.Wire == "bytes" { - p.enc = (*Buffer).enc_struct_message - p.dec = (*Buffer).dec_struct_message - p.size = size_struct_message - } else { - p.enc = (*Buffer).enc_struct_group - p.dec = (*Buffer).dec_struct_group - p.size = size_struct_group - } } case reflect.Slice: - switch t2 := t1.Elem(); t2.Kind() { - default: - logNoSliceEnc(t1, t2) - break - case reflect.Bool: - if p.Packed { - p.enc = (*Buffer).enc_slice_packed_bool - p.size = size_slice_packed_bool - } else { - p.enc = (*Buffer).enc_slice_bool - p.size = size_slice_bool - } - p.dec = (*Buffer).dec_slice_bool - p.packedDec = (*Buffer).dec_slice_packed_bool - case reflect.Int32: - if p.Packed { - p.enc = (*Buffer).enc_slice_packed_int32 - p.size = size_slice_packed_int32 - } else { - p.enc = (*Buffer).enc_slice_int32 - p.size = size_slice_int32 - } - p.dec = (*Buffer).dec_slice_int32 - p.packedDec = (*Buffer).dec_slice_packed_int32 - case reflect.Uint32: - if p.Packed { - p.enc = (*Buffer).enc_slice_packed_uint32 - p.size = size_slice_packed_uint32 - } else { - p.enc = (*Buffer).enc_slice_uint32 - p.size = size_slice_uint32 - } - p.dec = (*Buffer).dec_slice_int32 - p.packedDec = (*Buffer).dec_slice_packed_int32 - case reflect.Int64, reflect.Uint64: - if p.Packed { - p.enc = (*Buffer).enc_slice_packed_int64 - p.size = size_slice_packed_int64 - } else { - p.enc = (*Buffer).enc_slice_int64 - p.size = size_slice_int64 - } - p.dec = (*Buffer).dec_slice_int64 - p.packedDec = (*Buffer).dec_slice_packed_int64 - case reflect.Uint8: - p.dec = (*Buffer).dec_slice_byte - if p.proto3 { - p.enc = (*Buffer).enc_proto3_slice_byte - p.size = size_proto3_slice_byte - } else { - p.enc = (*Buffer).enc_slice_byte - p.size = size_slice_byte - } - case reflect.Float32, reflect.Float64: - switch t2.Bits() { - case 32: - // can just treat them as bits - if p.Packed { - p.enc = (*Buffer).enc_slice_packed_uint32 - p.size = size_slice_packed_uint32 - } else { - p.enc = (*Buffer).enc_slice_uint32 - p.size = size_slice_uint32 - } - p.dec = (*Buffer).dec_slice_int32 - p.packedDec = (*Buffer).dec_slice_packed_int32 - case 64: - // can just treat them as bits - if p.Packed { - p.enc = (*Buffer).enc_slice_packed_int64 - p.size = size_slice_packed_int64 - } else { - p.enc = (*Buffer).enc_slice_int64 - p.size = size_slice_int64 - } - p.dec = (*Buffer).dec_slice_int64 - p.packedDec = (*Buffer).dec_slice_packed_int64 - default: - logNoSliceEnc(t1, t2) - break - } - case reflect.String: - p.enc = (*Buffer).enc_slice_string - p.dec = (*Buffer).dec_slice_string - p.size = size_slice_string - case reflect.Ptr: - switch t3 := t2.Elem(); t3.Kind() { - default: - fmt.Fprintf(os.Stderr, "proto: no ptr oenc for %T -> %T -> %T\n", t1, t2, t3) - break - case reflect.Struct: - p.stype = t2.Elem() - p.isMarshaler = isMarshaler(t2) - p.isUnmarshaler = isUnmarshaler(t2) - if p.Wire == "bytes" { - p.enc = (*Buffer).enc_slice_struct_message - p.dec = (*Buffer).dec_slice_struct_message - p.size = size_slice_struct_message - } else { - p.enc = (*Buffer).enc_slice_struct_group - p.dec = (*Buffer).dec_slice_struct_group - p.size = size_slice_struct_group - } - } - case reflect.Slice: - switch t2.Elem().Kind() { - default: - fmt.Fprintf(os.Stderr, "proto: no slice elem oenc for %T -> %T -> %T\n", t1, t2, t2.Elem()) - break - case reflect.Uint8: - p.enc = (*Buffer).enc_slice_slice_byte - p.dec = (*Buffer).dec_slice_slice_byte - p.size = size_slice_slice_byte - } + if t2 := t1.Elem(); t2.Kind() == reflect.Ptr && t2.Elem().Kind() == reflect.Struct { + p.stype = t2.Elem() } case reflect.Map: - p.enc = (*Buffer).enc_new_map - p.dec = (*Buffer).dec_new_map - p.size = size_new_map - p.mtype = t1 - p.mkeyprop = &Properties{} - p.mkeyprop.init(reflect.PtrTo(p.mtype.Key()), "Key", f.Tag.Get("protobuf_key"), nil, lockGetProp) - p.mvalprop = &Properties{} + p.MapKeyProp = &Properties{} + p.MapKeyProp.init(reflect.PtrTo(p.mtype.Key()), "Key", f.Tag.Get("protobuf_key"), nil, lockGetProp) + p.MapValProp = &Properties{} vtype := p.mtype.Elem() if vtype.Kind() != reflect.Ptr && vtype.Kind() != reflect.Slice { // The value type is not a message (*T) or bytes ([]byte), // so we need encoders for the pointer to this type. vtype = reflect.PtrTo(vtype) } - p.mvalprop.init(vtype, "Value", f.Tag.Get("protobuf_val"), nil, lockGetProp) + p.MapValProp.init(vtype, "Value", f.Tag.Get("protobuf_val"), nil, lockGetProp) } - // precalculate tag code - wire := p.WireType - if p.Packed { - wire = WireBytes - } - x := uint32(p.Tag)<<3 | uint32(wire) - i := 0 - for i = 0; x > 127; i++ { - p.tagbuf[i] = 0x80 | uint8(x&0x7F) - x >>= 7 - } - p.tagbuf[i] = uint8(x) - p.tagcode = p.tagbuf[0 : i+1] - if p.stype != nil { if lockGetProp { p.sprop = GetProperties(p.stype) @@ -586,32 +297,9 @@ func (p *Properties) setEncAndDec(typ reflect.Type, f *reflect.StructField, lock } var ( - marshalerType = reflect.TypeOf((*Marshaler)(nil)).Elem() - unmarshalerType = reflect.TypeOf((*Unmarshaler)(nil)).Elem() + marshalerType = reflect.TypeOf((*Marshaler)(nil)).Elem() ) -// isMarshaler reports whether type t implements Marshaler. -func isMarshaler(t reflect.Type) bool { - // We're checking for (likely) pointer-receiver methods - // so if t is not a pointer, something is very wrong. - // The calls above only invoke isMarshaler on pointer types. - if t.Kind() != reflect.Ptr { - panic("proto: misuse of isMarshaler") - } - return t.Implements(marshalerType) -} - -// isUnmarshaler reports whether type t implements Unmarshaler. -func isUnmarshaler(t reflect.Type) bool { - // We're checking for (likely) pointer-receiver methods - // so if t is not a pointer, something is very wrong. - // The calls above only invoke isUnmarshaler on pointer types. - if t.Kind() != reflect.Ptr { - panic("proto: misuse of isUnmarshaler") - } - return t.Implements(unmarshalerType) -} - // Init populates the properties from a protocol buffer struct tag. func (p *Properties) Init(typ reflect.Type, name, tag string, f *reflect.StructField) { p.init(typ, name, tag, f, true) @@ -621,14 +309,11 @@ func (p *Properties) init(typ reflect.Type, name, tag string, f *reflect.StructF // "bytes,49,opt,def=hello!" p.Name = name p.OrigName = name - if f != nil { - p.field = toField(f) - } if tag == "" { return } p.Parse(tag) - p.setEncAndDec(typ, f, lockGetProp) + p.setFieldProps(typ, f, lockGetProp) } var ( @@ -649,9 +334,6 @@ func GetProperties(t reflect.Type) *StructProperties { sprop, ok := propertiesMap[t] propertiesMu.RUnlock() if ok { - if collectStats { - stats.Chit++ - } return sprop } @@ -664,23 +346,14 @@ func GetProperties(t reflect.Type) *StructProperties { // getPropertiesLocked requires that propertiesMu is held. func getPropertiesLocked(t reflect.Type) *StructProperties { if prop, ok := propertiesMap[t]; ok { - if collectStats { - stats.Chit++ - } return prop } - if collectStats { - stats.Cmiss++ - } prop := new(StructProperties) // in case of recursive protos, fill this in now. propertiesMap[t] = prop // build properties - prop.extendable = reflect.PtrTo(t).Implements(extendableProtoType) || - reflect.PtrTo(t).Implements(extendableProtoV1Type) - prop.unrecField = invalidField prop.Prop = make([]*Properties, t.NumField()) prop.order = make([]int, t.NumField()) @@ -690,17 +363,6 @@ func getPropertiesLocked(t reflect.Type) *StructProperties { name := f.Name p.init(f.Type, name, f.Tag.Get("protobuf"), &f, false) - if f.Name == "XXX_InternalExtensions" { // special case - p.enc = (*Buffer).enc_exts - p.dec = nil // not needed - p.size = size_exts - } else if f.Name == "XXX_extensions" { // special case - p.enc = (*Buffer).enc_map - p.dec = nil // not needed - p.size = size_map - } else if f.Name == "XXX_unrecognized" { // special case - prop.unrecField = toField(&f) - } oneof := f.Tag.Get("protobuf_oneof") // special case if oneof != "" { // Oneof fields don't use the traditional protobuf tag. @@ -715,9 +377,6 @@ func getPropertiesLocked(t reflect.Type) *StructProperties { } print("\n") } - if p.enc == nil && !strings.HasPrefix(f.Name, "XXX_") && oneof == "" { - fmt.Fprintln(os.Stderr, "proto: no encoder for", f.Name, f.Type.String(), "[GetProperties]") - } } // Re-order prop.order. @@ -728,8 +387,7 @@ func getPropertiesLocked(t reflect.Type) *StructProperties { } if om, ok := reflect.Zero(reflect.PtrTo(t)).Interface().(oneofMessage); ok { var oots []interface{} - prop.oneofMarshaler, prop.oneofUnmarshaler, prop.oneofSizer, oots = om.XXX_OneofFuncs() - prop.stype = t + _, _, _, oots = om.XXX_OneofFuncs() // Interpret oneof metadata. prop.OneofTypes = make(map[string]*OneofProperties) @@ -779,30 +437,6 @@ func getPropertiesLocked(t reflect.Type) *StructProperties { return prop } -// Return the Properties object for the x[0]'th field of the structure. -func propByIndex(t reflect.Type, x []int) *Properties { - if len(x) != 1 { - fmt.Fprintf(os.Stderr, "proto: field index dimension %d (not 1) for type %s\n", len(x), t) - return nil - } - prop := GetProperties(t) - return prop.Prop[x[0]] -} - -// Get the address and type of a pointer to a struct from an interface. -func getbase(pb Message) (t reflect.Type, b structPointer, err error) { - if pb == nil { - err = ErrNil - return - } - // get the reflect type of the pointer to the struct. - t = reflect.TypeOf(pb) - // get the address of the struct. - value := reflect.ValueOf(pb) - b = toStructPointer(value) - return -} - // A global registry of enum types. // The generated code will register the generated maps by calling RegisterEnum. @@ -826,20 +460,42 @@ func EnumValueMap(enumType string) map[string]int32 { // A registry of all linked message types. // The string is a fully-qualified proto name ("pkg.Message"). var ( - protoTypes = make(map[string]reflect.Type) - revProtoTypes = make(map[reflect.Type]string) + protoTypedNils = make(map[string]Message) // a map from proto names to typed nil pointers + protoMapTypes = make(map[string]reflect.Type) // a map from proto names to map types + revProtoTypes = make(map[reflect.Type]string) ) // RegisterType is called from generated code and maps from the fully qualified // proto name to the type (pointer to struct) of the protocol buffer. func RegisterType(x Message, name string) { - if _, ok := protoTypes[name]; ok { + if _, ok := protoTypedNils[name]; ok { // TODO: Some day, make this a panic. log.Printf("proto: duplicate proto type registered: %s", name) return } t := reflect.TypeOf(x) - protoTypes[name] = t + if v := reflect.ValueOf(x); v.Kind() == reflect.Ptr && v.Pointer() == 0 { + // Generated code always calls RegisterType with nil x. + // This check is just for extra safety. + protoTypedNils[name] = x + } else { + protoTypedNils[name] = reflect.Zero(t).Interface().(Message) + } + revProtoTypes[t] = name +} + +// RegisterMapType is called from generated code and maps from the fully qualified +// proto name to the native map type of the proto map definition. +func RegisterMapType(x interface{}, name string) { + if reflect.TypeOf(x).Kind() != reflect.Map { + panic(fmt.Sprintf("RegisterMapType(%T, %q); want map", x, name)) + } + if _, ok := protoMapTypes[name]; ok { + log.Printf("proto: duplicate proto type registered: %s", name) + return + } + t := reflect.TypeOf(x) + protoMapTypes[name] = t revProtoTypes[t] = name } @@ -855,7 +511,14 @@ func MessageName(x Message) string { } // MessageType returns the message type (pointer to struct) for a named message. -func MessageType(name string) reflect.Type { return protoTypes[name] } +// The type is not guaranteed to implement proto.Message if the name refers to a +// map entry. +func MessageType(name string) reflect.Type { + if t, ok := protoTypedNils[name]; ok { + return reflect.TypeOf(t) + } + return protoMapTypes[name] +} // A registry of all linked proto files. var ( diff --git a/chaincode/abac/go/vendor/github.com/golang/protobuf/proto/table_marshal.go b/chaincode/abac/go/vendor/github.com/golang/protobuf/proto/table_marshal.go new file mode 100644 index 00000000..f3a2d16a --- /dev/null +++ b/chaincode/abac/go/vendor/github.com/golang/protobuf/proto/table_marshal.go @@ -0,0 +1,2767 @@ +// Go support for Protocol Buffers - Google's data interchange format +// +// Copyright 2016 The Go Authors. All rights reserved. +// https://github.com/golang/protobuf +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +package proto + +import ( + "errors" + "fmt" + "math" + "reflect" + "sort" + "strconv" + "strings" + "sync" + "sync/atomic" + "unicode/utf8" +) + +// a sizer takes a pointer to a field and the size of its tag, computes the size of +// the encoded data. +type sizer func(pointer, int) int + +// a marshaler takes a byte slice, a pointer to a field, and its tag (in wire format), +// marshals the field to the end of the slice, returns the slice and error (if any). +type marshaler func(b []byte, ptr pointer, wiretag uint64, deterministic bool) ([]byte, error) + +// marshalInfo is the information used for marshaling a message. +type marshalInfo struct { + typ reflect.Type + fields []*marshalFieldInfo + unrecognized field // offset of XXX_unrecognized + extensions field // offset of XXX_InternalExtensions + v1extensions field // offset of XXX_extensions + sizecache field // offset of XXX_sizecache + initialized int32 // 0 -- only typ is set, 1 -- fully initialized + messageset bool // uses message set wire format + hasmarshaler bool // has custom marshaler + sync.RWMutex // protect extElems map, also for initialization + extElems map[int32]*marshalElemInfo // info of extension elements +} + +// marshalFieldInfo is the information used for marshaling a field of a message. +type marshalFieldInfo struct { + field field + wiretag uint64 // tag in wire format + tagsize int // size of tag in wire format + sizer sizer + marshaler marshaler + isPointer bool + required bool // field is required + name string // name of the field, for error reporting + oneofElems map[reflect.Type]*marshalElemInfo // info of oneof elements +} + +// marshalElemInfo is the information used for marshaling an extension or oneof element. +type marshalElemInfo struct { + wiretag uint64 // tag in wire format + tagsize int // size of tag in wire format + sizer sizer + marshaler marshaler + isptr bool // elem is pointer typed, thus interface of this type is a direct interface (extension only) +} + +var ( + marshalInfoMap = map[reflect.Type]*marshalInfo{} + marshalInfoLock sync.Mutex +) + +// getMarshalInfo returns the information to marshal a given type of message. +// The info it returns may not necessarily initialized. +// t is the type of the message (NOT the pointer to it). +func getMarshalInfo(t reflect.Type) *marshalInfo { + marshalInfoLock.Lock() + u, ok := marshalInfoMap[t] + if !ok { + u = &marshalInfo{typ: t} + marshalInfoMap[t] = u + } + marshalInfoLock.Unlock() + return u +} + +// Size is the entry point from generated code, +// and should be ONLY called by generated code. +// It computes the size of encoded data of msg. +// a is a pointer to a place to store cached marshal info. +func (a *InternalMessageInfo) Size(msg Message) int { + u := getMessageMarshalInfo(msg, a) + ptr := toPointer(&msg) + if ptr.isNil() { + // We get here if msg is a typed nil ((*SomeMessage)(nil)), + // so it satisfies the interface, and msg == nil wouldn't + // catch it. We don't want crash in this case. + return 0 + } + return u.size(ptr) +} + +// Marshal is the entry point from generated code, +// and should be ONLY called by generated code. +// It marshals msg to the end of b. +// a is a pointer to a place to store cached marshal info. +func (a *InternalMessageInfo) Marshal(b []byte, msg Message, deterministic bool) ([]byte, error) { + u := getMessageMarshalInfo(msg, a) + ptr := toPointer(&msg) + if ptr.isNil() { + // We get here if msg is a typed nil ((*SomeMessage)(nil)), + // so it satisfies the interface, and msg == nil wouldn't + // catch it. We don't want crash in this case. + return b, ErrNil + } + return u.marshal(b, ptr, deterministic) +} + +func getMessageMarshalInfo(msg interface{}, a *InternalMessageInfo) *marshalInfo { + // u := a.marshal, but atomically. + // We use an atomic here to ensure memory consistency. + u := atomicLoadMarshalInfo(&a.marshal) + if u == nil { + // Get marshal information from type of message. + t := reflect.ValueOf(msg).Type() + if t.Kind() != reflect.Ptr { + panic(fmt.Sprintf("cannot handle non-pointer message type %v", t)) + } + u = getMarshalInfo(t.Elem()) + // Store it in the cache for later users. + // a.marshal = u, but atomically. + atomicStoreMarshalInfo(&a.marshal, u) + } + return u +} + +// size is the main function to compute the size of the encoded data of a message. +// ptr is the pointer to the message. +func (u *marshalInfo) size(ptr pointer) int { + if atomic.LoadInt32(&u.initialized) == 0 { + u.computeMarshalInfo() + } + + // If the message can marshal itself, let it do it, for compatibility. + // NOTE: This is not efficient. + if u.hasmarshaler { + m := ptr.asPointerTo(u.typ).Interface().(Marshaler) + b, _ := m.Marshal() + return len(b) + } + + n := 0 + for _, f := range u.fields { + if f.isPointer && ptr.offset(f.field).getPointer().isNil() { + // nil pointer always marshals to nothing + continue + } + n += f.sizer(ptr.offset(f.field), f.tagsize) + } + if u.extensions.IsValid() { + e := ptr.offset(u.extensions).toExtensions() + if u.messageset { + n += u.sizeMessageSet(e) + } else { + n += u.sizeExtensions(e) + } + } + if u.v1extensions.IsValid() { + m := *ptr.offset(u.v1extensions).toOldExtensions() + n += u.sizeV1Extensions(m) + } + if u.unrecognized.IsValid() { + s := *ptr.offset(u.unrecognized).toBytes() + n += len(s) + } + // cache the result for use in marshal + if u.sizecache.IsValid() { + atomic.StoreInt32(ptr.offset(u.sizecache).toInt32(), int32(n)) + } + return n +} + +// cachedsize gets the size from cache. If there is no cache (i.e. message is not generated), +// fall back to compute the size. +func (u *marshalInfo) cachedsize(ptr pointer) int { + if u.sizecache.IsValid() { + return int(atomic.LoadInt32(ptr.offset(u.sizecache).toInt32())) + } + return u.size(ptr) +} + +// marshal is the main function to marshal a message. It takes a byte slice and appends +// the encoded data to the end of the slice, returns the slice and error (if any). +// ptr is the pointer to the message. +// If deterministic is true, map is marshaled in deterministic order. +func (u *marshalInfo) marshal(b []byte, ptr pointer, deterministic bool) ([]byte, error) { + if atomic.LoadInt32(&u.initialized) == 0 { + u.computeMarshalInfo() + } + + // If the message can marshal itself, let it do it, for compatibility. + // NOTE: This is not efficient. + if u.hasmarshaler { + m := ptr.asPointerTo(u.typ).Interface().(Marshaler) + b1, err := m.Marshal() + b = append(b, b1...) + return b, err + } + + var err, errLater error + // The old marshaler encodes extensions at beginning. + if u.extensions.IsValid() { + e := ptr.offset(u.extensions).toExtensions() + if u.messageset { + b, err = u.appendMessageSet(b, e, deterministic) + } else { + b, err = u.appendExtensions(b, e, deterministic) + } + if err != nil { + return b, err + } + } + if u.v1extensions.IsValid() { + m := *ptr.offset(u.v1extensions).toOldExtensions() + b, err = u.appendV1Extensions(b, m, deterministic) + if err != nil { + return b, err + } + } + for _, f := range u.fields { + if f.required { + if ptr.offset(f.field).getPointer().isNil() { + // Required field is not set. + // We record the error but keep going, to give a complete marshaling. + if errLater == nil { + errLater = &RequiredNotSetError{f.name} + } + continue + } + } + if f.isPointer && ptr.offset(f.field).getPointer().isNil() { + // nil pointer always marshals to nothing + continue + } + b, err = f.marshaler(b, ptr.offset(f.field), f.wiretag, deterministic) + if err != nil { + if err1, ok := err.(*RequiredNotSetError); ok { + // Required field in submessage is not set. + // We record the error but keep going, to give a complete marshaling. + if errLater == nil { + errLater = &RequiredNotSetError{f.name + "." + err1.field} + } + continue + } + if err == errRepeatedHasNil { + err = errors.New("proto: repeated field " + f.name + " has nil element") + } + if err == errInvalidUTF8 { + if errLater == nil { + fullName := revProtoTypes[reflect.PtrTo(u.typ)] + "." + f.name + errLater = &invalidUTF8Error{fullName} + } + continue + } + return b, err + } + } + if u.unrecognized.IsValid() { + s := *ptr.offset(u.unrecognized).toBytes() + b = append(b, s...) + } + return b, errLater +} + +// computeMarshalInfo initializes the marshal info. +func (u *marshalInfo) computeMarshalInfo() { + u.Lock() + defer u.Unlock() + if u.initialized != 0 { // non-atomic read is ok as it is protected by the lock + return + } + + t := u.typ + u.unrecognized = invalidField + u.extensions = invalidField + u.v1extensions = invalidField + u.sizecache = invalidField + + // If the message can marshal itself, let it do it, for compatibility. + // NOTE: This is not efficient. + if reflect.PtrTo(t).Implements(marshalerType) { + u.hasmarshaler = true + atomic.StoreInt32(&u.initialized, 1) + return + } + + // get oneof implementers + var oneofImplementers []interface{} + if m, ok := reflect.Zero(reflect.PtrTo(t)).Interface().(oneofMessage); ok { + _, _, _, oneofImplementers = m.XXX_OneofFuncs() + } + + n := t.NumField() + + // deal with XXX fields first + for i := 0; i < t.NumField(); i++ { + f := t.Field(i) + if !strings.HasPrefix(f.Name, "XXX_") { + continue + } + switch f.Name { + case "XXX_sizecache": + u.sizecache = toField(&f) + case "XXX_unrecognized": + u.unrecognized = toField(&f) + case "XXX_InternalExtensions": + u.extensions = toField(&f) + u.messageset = f.Tag.Get("protobuf_messageset") == "1" + case "XXX_extensions": + u.v1extensions = toField(&f) + case "XXX_NoUnkeyedLiteral": + // nothing to do + default: + panic("unknown XXX field: " + f.Name) + } + n-- + } + + // normal fields + fields := make([]marshalFieldInfo, n) // batch allocation + u.fields = make([]*marshalFieldInfo, 0, n) + for i, j := 0, 0; i < t.NumField(); i++ { + f := t.Field(i) + + if strings.HasPrefix(f.Name, "XXX_") { + continue + } + field := &fields[j] + j++ + field.name = f.Name + u.fields = append(u.fields, field) + if f.Tag.Get("protobuf_oneof") != "" { + field.computeOneofFieldInfo(&f, oneofImplementers) + continue + } + if f.Tag.Get("protobuf") == "" { + // field has no tag (not in generated message), ignore it + u.fields = u.fields[:len(u.fields)-1] + j-- + continue + } + field.computeMarshalFieldInfo(&f) + } + + // fields are marshaled in tag order on the wire. + sort.Sort(byTag(u.fields)) + + atomic.StoreInt32(&u.initialized, 1) +} + +// helper for sorting fields by tag +type byTag []*marshalFieldInfo + +func (a byTag) Len() int { return len(a) } +func (a byTag) Swap(i, j int) { a[i], a[j] = a[j], a[i] } +func (a byTag) Less(i, j int) bool { return a[i].wiretag < a[j].wiretag } + +// getExtElemInfo returns the information to marshal an extension element. +// The info it returns is initialized. +func (u *marshalInfo) getExtElemInfo(desc *ExtensionDesc) *marshalElemInfo { + // get from cache first + u.RLock() + e, ok := u.extElems[desc.Field] + u.RUnlock() + if ok { + return e + } + + t := reflect.TypeOf(desc.ExtensionType) // pointer or slice to basic type or struct + tags := strings.Split(desc.Tag, ",") + tag, err := strconv.Atoi(tags[1]) + if err != nil { + panic("tag is not an integer") + } + wt := wiretype(tags[0]) + sizer, marshaler := typeMarshaler(t, tags, false, false) + e = &marshalElemInfo{ + wiretag: uint64(tag)<<3 | wt, + tagsize: SizeVarint(uint64(tag) << 3), + sizer: sizer, + marshaler: marshaler, + isptr: t.Kind() == reflect.Ptr, + } + + // update cache + u.Lock() + if u.extElems == nil { + u.extElems = make(map[int32]*marshalElemInfo) + } + u.extElems[desc.Field] = e + u.Unlock() + return e +} + +// computeMarshalFieldInfo fills up the information to marshal a field. +func (fi *marshalFieldInfo) computeMarshalFieldInfo(f *reflect.StructField) { + // parse protobuf tag of the field. + // tag has format of "bytes,49,opt,name=foo,def=hello!" + tags := strings.Split(f.Tag.Get("protobuf"), ",") + if tags[0] == "" { + return + } + tag, err := strconv.Atoi(tags[1]) + if err != nil { + panic("tag is not an integer") + } + wt := wiretype(tags[0]) + if tags[2] == "req" { + fi.required = true + } + fi.setTag(f, tag, wt) + fi.setMarshaler(f, tags) +} + +func (fi *marshalFieldInfo) computeOneofFieldInfo(f *reflect.StructField, oneofImplementers []interface{}) { + fi.field = toField(f) + fi.wiretag = math.MaxInt32 // Use a large tag number, make oneofs sorted at the end. This tag will not appear on the wire. + fi.isPointer = true + fi.sizer, fi.marshaler = makeOneOfMarshaler(fi, f) + fi.oneofElems = make(map[reflect.Type]*marshalElemInfo) + + ityp := f.Type // interface type + for _, o := range oneofImplementers { + t := reflect.TypeOf(o) + if !t.Implements(ityp) { + continue + } + sf := t.Elem().Field(0) // oneof implementer is a struct with a single field + tags := strings.Split(sf.Tag.Get("protobuf"), ",") + tag, err := strconv.Atoi(tags[1]) + if err != nil { + panic("tag is not an integer") + } + wt := wiretype(tags[0]) + sizer, marshaler := typeMarshaler(sf.Type, tags, false, true) // oneof should not omit any zero value + fi.oneofElems[t.Elem()] = &marshalElemInfo{ + wiretag: uint64(tag)<<3 | wt, + tagsize: SizeVarint(uint64(tag) << 3), + sizer: sizer, + marshaler: marshaler, + } + } +} + +type oneofMessage interface { + XXX_OneofFuncs() (func(Message, *Buffer) error, func(Message, int, int, *Buffer) (bool, error), func(Message) int, []interface{}) +} + +// wiretype returns the wire encoding of the type. +func wiretype(encoding string) uint64 { + switch encoding { + case "fixed32": + return WireFixed32 + case "fixed64": + return WireFixed64 + case "varint", "zigzag32", "zigzag64": + return WireVarint + case "bytes": + return WireBytes + case "group": + return WireStartGroup + } + panic("unknown wire type " + encoding) +} + +// setTag fills up the tag (in wire format) and its size in the info of a field. +func (fi *marshalFieldInfo) setTag(f *reflect.StructField, tag int, wt uint64) { + fi.field = toField(f) + fi.wiretag = uint64(tag)<<3 | wt + fi.tagsize = SizeVarint(uint64(tag) << 3) +} + +// setMarshaler fills up the sizer and marshaler in the info of a field. +func (fi *marshalFieldInfo) setMarshaler(f *reflect.StructField, tags []string) { + switch f.Type.Kind() { + case reflect.Map: + // map field + fi.isPointer = true + fi.sizer, fi.marshaler = makeMapMarshaler(f) + return + case reflect.Ptr, reflect.Slice: + fi.isPointer = true + } + fi.sizer, fi.marshaler = typeMarshaler(f.Type, tags, true, false) +} + +// typeMarshaler returns the sizer and marshaler of a given field. +// t is the type of the field. +// tags is the generated "protobuf" tag of the field. +// If nozero is true, zero value is not marshaled to the wire. +// If oneof is true, it is a oneof field. +func typeMarshaler(t reflect.Type, tags []string, nozero, oneof bool) (sizer, marshaler) { + encoding := tags[0] + + pointer := false + slice := false + if t.Kind() == reflect.Slice && t.Elem().Kind() != reflect.Uint8 { + slice = true + t = t.Elem() + } + if t.Kind() == reflect.Ptr { + pointer = true + t = t.Elem() + } + + packed := false + proto3 := false + validateUTF8 := true + for i := 2; i < len(tags); i++ { + if tags[i] == "packed" { + packed = true + } + if tags[i] == "proto3" { + proto3 = true + } + } + validateUTF8 = validateUTF8 && proto3 + + switch t.Kind() { + case reflect.Bool: + if pointer { + return sizeBoolPtr, appendBoolPtr + } + if slice { + if packed { + return sizeBoolPackedSlice, appendBoolPackedSlice + } + return sizeBoolSlice, appendBoolSlice + } + if nozero { + return sizeBoolValueNoZero, appendBoolValueNoZero + } + return sizeBoolValue, appendBoolValue + case reflect.Uint32: + switch encoding { + case "fixed32": + if pointer { + return sizeFixed32Ptr, appendFixed32Ptr + } + if slice { + if packed { + return sizeFixed32PackedSlice, appendFixed32PackedSlice + } + return sizeFixed32Slice, appendFixed32Slice + } + if nozero { + return sizeFixed32ValueNoZero, appendFixed32ValueNoZero + } + return sizeFixed32Value, appendFixed32Value + case "varint": + if pointer { + return sizeVarint32Ptr, appendVarint32Ptr + } + if slice { + if packed { + return sizeVarint32PackedSlice, appendVarint32PackedSlice + } + return sizeVarint32Slice, appendVarint32Slice + } + if nozero { + return sizeVarint32ValueNoZero, appendVarint32ValueNoZero + } + return sizeVarint32Value, appendVarint32Value + } + case reflect.Int32: + switch encoding { + case "fixed32": + if pointer { + return sizeFixedS32Ptr, appendFixedS32Ptr + } + if slice { + if packed { + return sizeFixedS32PackedSlice, appendFixedS32PackedSlice + } + return sizeFixedS32Slice, appendFixedS32Slice + } + if nozero { + return sizeFixedS32ValueNoZero, appendFixedS32ValueNoZero + } + return sizeFixedS32Value, appendFixedS32Value + case "varint": + if pointer { + return sizeVarintS32Ptr, appendVarintS32Ptr + } + if slice { + if packed { + return sizeVarintS32PackedSlice, appendVarintS32PackedSlice + } + return sizeVarintS32Slice, appendVarintS32Slice + } + if nozero { + return sizeVarintS32ValueNoZero, appendVarintS32ValueNoZero + } + return sizeVarintS32Value, appendVarintS32Value + case "zigzag32": + if pointer { + return sizeZigzag32Ptr, appendZigzag32Ptr + } + if slice { + if packed { + return sizeZigzag32PackedSlice, appendZigzag32PackedSlice + } + return sizeZigzag32Slice, appendZigzag32Slice + } + if nozero { + return sizeZigzag32ValueNoZero, appendZigzag32ValueNoZero + } + return sizeZigzag32Value, appendZigzag32Value + } + case reflect.Uint64: + switch encoding { + case "fixed64": + if pointer { + return sizeFixed64Ptr, appendFixed64Ptr + } + if slice { + if packed { + return sizeFixed64PackedSlice, appendFixed64PackedSlice + } + return sizeFixed64Slice, appendFixed64Slice + } + if nozero { + return sizeFixed64ValueNoZero, appendFixed64ValueNoZero + } + return sizeFixed64Value, appendFixed64Value + case "varint": + if pointer { + return sizeVarint64Ptr, appendVarint64Ptr + } + if slice { + if packed { + return sizeVarint64PackedSlice, appendVarint64PackedSlice + } + return sizeVarint64Slice, appendVarint64Slice + } + if nozero { + return sizeVarint64ValueNoZero, appendVarint64ValueNoZero + } + return sizeVarint64Value, appendVarint64Value + } + case reflect.Int64: + switch encoding { + case "fixed64": + if pointer { + return sizeFixedS64Ptr, appendFixedS64Ptr + } + if slice { + if packed { + return sizeFixedS64PackedSlice, appendFixedS64PackedSlice + } + return sizeFixedS64Slice, appendFixedS64Slice + } + if nozero { + return sizeFixedS64ValueNoZero, appendFixedS64ValueNoZero + } + return sizeFixedS64Value, appendFixedS64Value + case "varint": + if pointer { + return sizeVarintS64Ptr, appendVarintS64Ptr + } + if slice { + if packed { + return sizeVarintS64PackedSlice, appendVarintS64PackedSlice + } + return sizeVarintS64Slice, appendVarintS64Slice + } + if nozero { + return sizeVarintS64ValueNoZero, appendVarintS64ValueNoZero + } + return sizeVarintS64Value, appendVarintS64Value + case "zigzag64": + if pointer { + return sizeZigzag64Ptr, appendZigzag64Ptr + } + if slice { + if packed { + return sizeZigzag64PackedSlice, appendZigzag64PackedSlice + } + return sizeZigzag64Slice, appendZigzag64Slice + } + if nozero { + return sizeZigzag64ValueNoZero, appendZigzag64ValueNoZero + } + return sizeZigzag64Value, appendZigzag64Value + } + case reflect.Float32: + if pointer { + return sizeFloat32Ptr, appendFloat32Ptr + } + if slice { + if packed { + return sizeFloat32PackedSlice, appendFloat32PackedSlice + } + return sizeFloat32Slice, appendFloat32Slice + } + if nozero { + return sizeFloat32ValueNoZero, appendFloat32ValueNoZero + } + return sizeFloat32Value, appendFloat32Value + case reflect.Float64: + if pointer { + return sizeFloat64Ptr, appendFloat64Ptr + } + if slice { + if packed { + return sizeFloat64PackedSlice, appendFloat64PackedSlice + } + return sizeFloat64Slice, appendFloat64Slice + } + if nozero { + return sizeFloat64ValueNoZero, appendFloat64ValueNoZero + } + return sizeFloat64Value, appendFloat64Value + case reflect.String: + if validateUTF8 { + if pointer { + return sizeStringPtr, appendUTF8StringPtr + } + if slice { + return sizeStringSlice, appendUTF8StringSlice + } + if nozero { + return sizeStringValueNoZero, appendUTF8StringValueNoZero + } + return sizeStringValue, appendUTF8StringValue + } + if pointer { + return sizeStringPtr, appendStringPtr + } + if slice { + return sizeStringSlice, appendStringSlice + } + if nozero { + return sizeStringValueNoZero, appendStringValueNoZero + } + return sizeStringValue, appendStringValue + case reflect.Slice: + if slice { + return sizeBytesSlice, appendBytesSlice + } + if oneof { + // Oneof bytes field may also have "proto3" tag. + // We want to marshal it as a oneof field. Do this + // check before the proto3 check. + return sizeBytesOneof, appendBytesOneof + } + if proto3 { + return sizeBytes3, appendBytes3 + } + return sizeBytes, appendBytes + case reflect.Struct: + switch encoding { + case "group": + if slice { + return makeGroupSliceMarshaler(getMarshalInfo(t)) + } + return makeGroupMarshaler(getMarshalInfo(t)) + case "bytes": + if slice { + return makeMessageSliceMarshaler(getMarshalInfo(t)) + } + return makeMessageMarshaler(getMarshalInfo(t)) + } + } + panic(fmt.Sprintf("unknown or mismatched type: type: %v, wire type: %v", t, encoding)) +} + +// Below are functions to size/marshal a specific type of a field. +// They are stored in the field's info, and called by function pointers. +// They have type sizer or marshaler. + +func sizeFixed32Value(_ pointer, tagsize int) int { + return 4 + tagsize +} +func sizeFixed32ValueNoZero(ptr pointer, tagsize int) int { + v := *ptr.toUint32() + if v == 0 { + return 0 + } + return 4 + tagsize +} +func sizeFixed32Ptr(ptr pointer, tagsize int) int { + p := *ptr.toUint32Ptr() + if p == nil { + return 0 + } + return 4 + tagsize +} +func sizeFixed32Slice(ptr pointer, tagsize int) int { + s := *ptr.toUint32Slice() + return (4 + tagsize) * len(s) +} +func sizeFixed32PackedSlice(ptr pointer, tagsize int) int { + s := *ptr.toUint32Slice() + if len(s) == 0 { + return 0 + } + return 4*len(s) + SizeVarint(uint64(4*len(s))) + tagsize +} +func sizeFixedS32Value(_ pointer, tagsize int) int { + return 4 + tagsize +} +func sizeFixedS32ValueNoZero(ptr pointer, tagsize int) int { + v := *ptr.toInt32() + if v == 0 { + return 0 + } + return 4 + tagsize +} +func sizeFixedS32Ptr(ptr pointer, tagsize int) int { + p := ptr.getInt32Ptr() + if p == nil { + return 0 + } + return 4 + tagsize +} +func sizeFixedS32Slice(ptr pointer, tagsize int) int { + s := ptr.getInt32Slice() + return (4 + tagsize) * len(s) +} +func sizeFixedS32PackedSlice(ptr pointer, tagsize int) int { + s := ptr.getInt32Slice() + if len(s) == 0 { + return 0 + } + return 4*len(s) + SizeVarint(uint64(4*len(s))) + tagsize +} +func sizeFloat32Value(_ pointer, tagsize int) int { + return 4 + tagsize +} +func sizeFloat32ValueNoZero(ptr pointer, tagsize int) int { + v := math.Float32bits(*ptr.toFloat32()) + if v == 0 { + return 0 + } + return 4 + tagsize +} +func sizeFloat32Ptr(ptr pointer, tagsize int) int { + p := *ptr.toFloat32Ptr() + if p == nil { + return 0 + } + return 4 + tagsize +} +func sizeFloat32Slice(ptr pointer, tagsize int) int { + s := *ptr.toFloat32Slice() + return (4 + tagsize) * len(s) +} +func sizeFloat32PackedSlice(ptr pointer, tagsize int) int { + s := *ptr.toFloat32Slice() + if len(s) == 0 { + return 0 + } + return 4*len(s) + SizeVarint(uint64(4*len(s))) + tagsize +} +func sizeFixed64Value(_ pointer, tagsize int) int { + return 8 + tagsize +} +func sizeFixed64ValueNoZero(ptr pointer, tagsize int) int { + v := *ptr.toUint64() + if v == 0 { + return 0 + } + return 8 + tagsize +} +func sizeFixed64Ptr(ptr pointer, tagsize int) int { + p := *ptr.toUint64Ptr() + if p == nil { + return 0 + } + return 8 + tagsize +} +func sizeFixed64Slice(ptr pointer, tagsize int) int { + s := *ptr.toUint64Slice() + return (8 + tagsize) * len(s) +} +func sizeFixed64PackedSlice(ptr pointer, tagsize int) int { + s := *ptr.toUint64Slice() + if len(s) == 0 { + return 0 + } + return 8*len(s) + SizeVarint(uint64(8*len(s))) + tagsize +} +func sizeFixedS64Value(_ pointer, tagsize int) int { + return 8 + tagsize +} +func sizeFixedS64ValueNoZero(ptr pointer, tagsize int) int { + v := *ptr.toInt64() + if v == 0 { + return 0 + } + return 8 + tagsize +} +func sizeFixedS64Ptr(ptr pointer, tagsize int) int { + p := *ptr.toInt64Ptr() + if p == nil { + return 0 + } + return 8 + tagsize +} +func sizeFixedS64Slice(ptr pointer, tagsize int) int { + s := *ptr.toInt64Slice() + return (8 + tagsize) * len(s) +} +func sizeFixedS64PackedSlice(ptr pointer, tagsize int) int { + s := *ptr.toInt64Slice() + if len(s) == 0 { + return 0 + } + return 8*len(s) + SizeVarint(uint64(8*len(s))) + tagsize +} +func sizeFloat64Value(_ pointer, tagsize int) int { + return 8 + tagsize +} +func sizeFloat64ValueNoZero(ptr pointer, tagsize int) int { + v := math.Float64bits(*ptr.toFloat64()) + if v == 0 { + return 0 + } + return 8 + tagsize +} +func sizeFloat64Ptr(ptr pointer, tagsize int) int { + p := *ptr.toFloat64Ptr() + if p == nil { + return 0 + } + return 8 + tagsize +} +func sizeFloat64Slice(ptr pointer, tagsize int) int { + s := *ptr.toFloat64Slice() + return (8 + tagsize) * len(s) +} +func sizeFloat64PackedSlice(ptr pointer, tagsize int) int { + s := *ptr.toFloat64Slice() + if len(s) == 0 { + return 0 + } + return 8*len(s) + SizeVarint(uint64(8*len(s))) + tagsize +} +func sizeVarint32Value(ptr pointer, tagsize int) int { + v := *ptr.toUint32() + return SizeVarint(uint64(v)) + tagsize +} +func sizeVarint32ValueNoZero(ptr pointer, tagsize int) int { + v := *ptr.toUint32() + if v == 0 { + return 0 + } + return SizeVarint(uint64(v)) + tagsize +} +func sizeVarint32Ptr(ptr pointer, tagsize int) int { + p := *ptr.toUint32Ptr() + if p == nil { + return 0 + } + return SizeVarint(uint64(*p)) + tagsize +} +func sizeVarint32Slice(ptr pointer, tagsize int) int { + s := *ptr.toUint32Slice() + n := 0 + for _, v := range s { + n += SizeVarint(uint64(v)) + tagsize + } + return n +} +func sizeVarint32PackedSlice(ptr pointer, tagsize int) int { + s := *ptr.toUint32Slice() + if len(s) == 0 { + return 0 + } + n := 0 + for _, v := range s { + n += SizeVarint(uint64(v)) + } + return n + SizeVarint(uint64(n)) + tagsize +} +func sizeVarintS32Value(ptr pointer, tagsize int) int { + v := *ptr.toInt32() + return SizeVarint(uint64(v)) + tagsize +} +func sizeVarintS32ValueNoZero(ptr pointer, tagsize int) int { + v := *ptr.toInt32() + if v == 0 { + return 0 + } + return SizeVarint(uint64(v)) + tagsize +} +func sizeVarintS32Ptr(ptr pointer, tagsize int) int { + p := ptr.getInt32Ptr() + if p == nil { + return 0 + } + return SizeVarint(uint64(*p)) + tagsize +} +func sizeVarintS32Slice(ptr pointer, tagsize int) int { + s := ptr.getInt32Slice() + n := 0 + for _, v := range s { + n += SizeVarint(uint64(v)) + tagsize + } + return n +} +func sizeVarintS32PackedSlice(ptr pointer, tagsize int) int { + s := ptr.getInt32Slice() + if len(s) == 0 { + return 0 + } + n := 0 + for _, v := range s { + n += SizeVarint(uint64(v)) + } + return n + SizeVarint(uint64(n)) + tagsize +} +func sizeVarint64Value(ptr pointer, tagsize int) int { + v := *ptr.toUint64() + return SizeVarint(v) + tagsize +} +func sizeVarint64ValueNoZero(ptr pointer, tagsize int) int { + v := *ptr.toUint64() + if v == 0 { + return 0 + } + return SizeVarint(v) + tagsize +} +func sizeVarint64Ptr(ptr pointer, tagsize int) int { + p := *ptr.toUint64Ptr() + if p == nil { + return 0 + } + return SizeVarint(*p) + tagsize +} +func sizeVarint64Slice(ptr pointer, tagsize int) int { + s := *ptr.toUint64Slice() + n := 0 + for _, v := range s { + n += SizeVarint(v) + tagsize + } + return n +} +func sizeVarint64PackedSlice(ptr pointer, tagsize int) int { + s := *ptr.toUint64Slice() + if len(s) == 0 { + return 0 + } + n := 0 + for _, v := range s { + n += SizeVarint(v) + } + return n + SizeVarint(uint64(n)) + tagsize +} +func sizeVarintS64Value(ptr pointer, tagsize int) int { + v := *ptr.toInt64() + return SizeVarint(uint64(v)) + tagsize +} +func sizeVarintS64ValueNoZero(ptr pointer, tagsize int) int { + v := *ptr.toInt64() + if v == 0 { + return 0 + } + return SizeVarint(uint64(v)) + tagsize +} +func sizeVarintS64Ptr(ptr pointer, tagsize int) int { + p := *ptr.toInt64Ptr() + if p == nil { + return 0 + } + return SizeVarint(uint64(*p)) + tagsize +} +func sizeVarintS64Slice(ptr pointer, tagsize int) int { + s := *ptr.toInt64Slice() + n := 0 + for _, v := range s { + n += SizeVarint(uint64(v)) + tagsize + } + return n +} +func sizeVarintS64PackedSlice(ptr pointer, tagsize int) int { + s := *ptr.toInt64Slice() + if len(s) == 0 { + return 0 + } + n := 0 + for _, v := range s { + n += SizeVarint(uint64(v)) + } + return n + SizeVarint(uint64(n)) + tagsize +} +func sizeZigzag32Value(ptr pointer, tagsize int) int { + v := *ptr.toInt32() + return SizeVarint(uint64((uint32(v)<<1)^uint32((int32(v)>>31)))) + tagsize +} +func sizeZigzag32ValueNoZero(ptr pointer, tagsize int) int { + v := *ptr.toInt32() + if v == 0 { + return 0 + } + return SizeVarint(uint64((uint32(v)<<1)^uint32((int32(v)>>31)))) + tagsize +} +func sizeZigzag32Ptr(ptr pointer, tagsize int) int { + p := ptr.getInt32Ptr() + if p == nil { + return 0 + } + v := *p + return SizeVarint(uint64((uint32(v)<<1)^uint32((int32(v)>>31)))) + tagsize +} +func sizeZigzag32Slice(ptr pointer, tagsize int) int { + s := ptr.getInt32Slice() + n := 0 + for _, v := range s { + n += SizeVarint(uint64((uint32(v)<<1)^uint32((int32(v)>>31)))) + tagsize + } + return n +} +func sizeZigzag32PackedSlice(ptr pointer, tagsize int) int { + s := ptr.getInt32Slice() + if len(s) == 0 { + return 0 + } + n := 0 + for _, v := range s { + n += SizeVarint(uint64((uint32(v) << 1) ^ uint32((int32(v) >> 31)))) + } + return n + SizeVarint(uint64(n)) + tagsize +} +func sizeZigzag64Value(ptr pointer, tagsize int) int { + v := *ptr.toInt64() + return SizeVarint(uint64(v<<1)^uint64((int64(v)>>63))) + tagsize +} +func sizeZigzag64ValueNoZero(ptr pointer, tagsize int) int { + v := *ptr.toInt64() + if v == 0 { + return 0 + } + return SizeVarint(uint64(v<<1)^uint64((int64(v)>>63))) + tagsize +} +func sizeZigzag64Ptr(ptr pointer, tagsize int) int { + p := *ptr.toInt64Ptr() + if p == nil { + return 0 + } + v := *p + return SizeVarint(uint64(v<<1)^uint64((int64(v)>>63))) + tagsize +} +func sizeZigzag64Slice(ptr pointer, tagsize int) int { + s := *ptr.toInt64Slice() + n := 0 + for _, v := range s { + n += SizeVarint(uint64(v<<1)^uint64((int64(v)>>63))) + tagsize + } + return n +} +func sizeZigzag64PackedSlice(ptr pointer, tagsize int) int { + s := *ptr.toInt64Slice() + if len(s) == 0 { + return 0 + } + n := 0 + for _, v := range s { + n += SizeVarint(uint64(v<<1) ^ uint64((int64(v) >> 63))) + } + return n + SizeVarint(uint64(n)) + tagsize +} +func sizeBoolValue(_ pointer, tagsize int) int { + return 1 + tagsize +} +func sizeBoolValueNoZero(ptr pointer, tagsize int) int { + v := *ptr.toBool() + if !v { + return 0 + } + return 1 + tagsize +} +func sizeBoolPtr(ptr pointer, tagsize int) int { + p := *ptr.toBoolPtr() + if p == nil { + return 0 + } + return 1 + tagsize +} +func sizeBoolSlice(ptr pointer, tagsize int) int { + s := *ptr.toBoolSlice() + return (1 + tagsize) * len(s) +} +func sizeBoolPackedSlice(ptr pointer, tagsize int) int { + s := *ptr.toBoolSlice() + if len(s) == 0 { + return 0 + } + return len(s) + SizeVarint(uint64(len(s))) + tagsize +} +func sizeStringValue(ptr pointer, tagsize int) int { + v := *ptr.toString() + return len(v) + SizeVarint(uint64(len(v))) + tagsize +} +func sizeStringValueNoZero(ptr pointer, tagsize int) int { + v := *ptr.toString() + if v == "" { + return 0 + } + return len(v) + SizeVarint(uint64(len(v))) + tagsize +} +func sizeStringPtr(ptr pointer, tagsize int) int { + p := *ptr.toStringPtr() + if p == nil { + return 0 + } + v := *p + return len(v) + SizeVarint(uint64(len(v))) + tagsize +} +func sizeStringSlice(ptr pointer, tagsize int) int { + s := *ptr.toStringSlice() + n := 0 + for _, v := range s { + n += len(v) + SizeVarint(uint64(len(v))) + tagsize + } + return n +} +func sizeBytes(ptr pointer, tagsize int) int { + v := *ptr.toBytes() + if v == nil { + return 0 + } + return len(v) + SizeVarint(uint64(len(v))) + tagsize +} +func sizeBytes3(ptr pointer, tagsize int) int { + v := *ptr.toBytes() + if len(v) == 0 { + return 0 + } + return len(v) + SizeVarint(uint64(len(v))) + tagsize +} +func sizeBytesOneof(ptr pointer, tagsize int) int { + v := *ptr.toBytes() + return len(v) + SizeVarint(uint64(len(v))) + tagsize +} +func sizeBytesSlice(ptr pointer, tagsize int) int { + s := *ptr.toBytesSlice() + n := 0 + for _, v := range s { + n += len(v) + SizeVarint(uint64(len(v))) + tagsize + } + return n +} + +// appendFixed32 appends an encoded fixed32 to b. +func appendFixed32(b []byte, v uint32) []byte { + b = append(b, + byte(v), + byte(v>>8), + byte(v>>16), + byte(v>>24)) + return b +} + +// appendFixed64 appends an encoded fixed64 to b. +func appendFixed64(b []byte, v uint64) []byte { + b = append(b, + byte(v), + byte(v>>8), + byte(v>>16), + byte(v>>24), + byte(v>>32), + byte(v>>40), + byte(v>>48), + byte(v>>56)) + return b +} + +// appendVarint appends an encoded varint to b. +func appendVarint(b []byte, v uint64) []byte { + // TODO: make 1-byte (maybe 2-byte) case inline-able, once we + // have non-leaf inliner. + switch { + case v < 1<<7: + b = append(b, byte(v)) + case v < 1<<14: + b = append(b, + byte(v&0x7f|0x80), + byte(v>>7)) + case v < 1<<21: + b = append(b, + byte(v&0x7f|0x80), + byte((v>>7)&0x7f|0x80), + byte(v>>14)) + case v < 1<<28: + b = append(b, + byte(v&0x7f|0x80), + byte((v>>7)&0x7f|0x80), + byte((v>>14)&0x7f|0x80), + byte(v>>21)) + case v < 1<<35: + b = append(b, + byte(v&0x7f|0x80), + byte((v>>7)&0x7f|0x80), + byte((v>>14)&0x7f|0x80), + byte((v>>21)&0x7f|0x80), + byte(v>>28)) + case v < 1<<42: + b = append(b, + byte(v&0x7f|0x80), + byte((v>>7)&0x7f|0x80), + byte((v>>14)&0x7f|0x80), + byte((v>>21)&0x7f|0x80), + byte((v>>28)&0x7f|0x80), + byte(v>>35)) + case v < 1<<49: + b = append(b, + byte(v&0x7f|0x80), + byte((v>>7)&0x7f|0x80), + byte((v>>14)&0x7f|0x80), + byte((v>>21)&0x7f|0x80), + byte((v>>28)&0x7f|0x80), + byte((v>>35)&0x7f|0x80), + byte(v>>42)) + case v < 1<<56: + b = append(b, + byte(v&0x7f|0x80), + byte((v>>7)&0x7f|0x80), + byte((v>>14)&0x7f|0x80), + byte((v>>21)&0x7f|0x80), + byte((v>>28)&0x7f|0x80), + byte((v>>35)&0x7f|0x80), + byte((v>>42)&0x7f|0x80), + byte(v>>49)) + case v < 1<<63: + b = append(b, + byte(v&0x7f|0x80), + byte((v>>7)&0x7f|0x80), + byte((v>>14)&0x7f|0x80), + byte((v>>21)&0x7f|0x80), + byte((v>>28)&0x7f|0x80), + byte((v>>35)&0x7f|0x80), + byte((v>>42)&0x7f|0x80), + byte((v>>49)&0x7f|0x80), + byte(v>>56)) + default: + b = append(b, + byte(v&0x7f|0x80), + byte((v>>7)&0x7f|0x80), + byte((v>>14)&0x7f|0x80), + byte((v>>21)&0x7f|0x80), + byte((v>>28)&0x7f|0x80), + byte((v>>35)&0x7f|0x80), + byte((v>>42)&0x7f|0x80), + byte((v>>49)&0x7f|0x80), + byte((v>>56)&0x7f|0x80), + 1) + } + return b +} + +func appendFixed32Value(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + v := *ptr.toUint32() + b = appendVarint(b, wiretag) + b = appendFixed32(b, v) + return b, nil +} +func appendFixed32ValueNoZero(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + v := *ptr.toUint32() + if v == 0 { + return b, nil + } + b = appendVarint(b, wiretag) + b = appendFixed32(b, v) + return b, nil +} +func appendFixed32Ptr(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + p := *ptr.toUint32Ptr() + if p == nil { + return b, nil + } + b = appendVarint(b, wiretag) + b = appendFixed32(b, *p) + return b, nil +} +func appendFixed32Slice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + s := *ptr.toUint32Slice() + for _, v := range s { + b = appendVarint(b, wiretag) + b = appendFixed32(b, v) + } + return b, nil +} +func appendFixed32PackedSlice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + s := *ptr.toUint32Slice() + if len(s) == 0 { + return b, nil + } + b = appendVarint(b, wiretag&^7|WireBytes) + b = appendVarint(b, uint64(4*len(s))) + for _, v := range s { + b = appendFixed32(b, v) + } + return b, nil +} +func appendFixedS32Value(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + v := *ptr.toInt32() + b = appendVarint(b, wiretag) + b = appendFixed32(b, uint32(v)) + return b, nil +} +func appendFixedS32ValueNoZero(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + v := *ptr.toInt32() + if v == 0 { + return b, nil + } + b = appendVarint(b, wiretag) + b = appendFixed32(b, uint32(v)) + return b, nil +} +func appendFixedS32Ptr(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + p := ptr.getInt32Ptr() + if p == nil { + return b, nil + } + b = appendVarint(b, wiretag) + b = appendFixed32(b, uint32(*p)) + return b, nil +} +func appendFixedS32Slice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + s := ptr.getInt32Slice() + for _, v := range s { + b = appendVarint(b, wiretag) + b = appendFixed32(b, uint32(v)) + } + return b, nil +} +func appendFixedS32PackedSlice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + s := ptr.getInt32Slice() + if len(s) == 0 { + return b, nil + } + b = appendVarint(b, wiretag&^7|WireBytes) + b = appendVarint(b, uint64(4*len(s))) + for _, v := range s { + b = appendFixed32(b, uint32(v)) + } + return b, nil +} +func appendFloat32Value(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + v := math.Float32bits(*ptr.toFloat32()) + b = appendVarint(b, wiretag) + b = appendFixed32(b, v) + return b, nil +} +func appendFloat32ValueNoZero(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + v := math.Float32bits(*ptr.toFloat32()) + if v == 0 { + return b, nil + } + b = appendVarint(b, wiretag) + b = appendFixed32(b, v) + return b, nil +} +func appendFloat32Ptr(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + p := *ptr.toFloat32Ptr() + if p == nil { + return b, nil + } + b = appendVarint(b, wiretag) + b = appendFixed32(b, math.Float32bits(*p)) + return b, nil +} +func appendFloat32Slice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + s := *ptr.toFloat32Slice() + for _, v := range s { + b = appendVarint(b, wiretag) + b = appendFixed32(b, math.Float32bits(v)) + } + return b, nil +} +func appendFloat32PackedSlice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + s := *ptr.toFloat32Slice() + if len(s) == 0 { + return b, nil + } + b = appendVarint(b, wiretag&^7|WireBytes) + b = appendVarint(b, uint64(4*len(s))) + for _, v := range s { + b = appendFixed32(b, math.Float32bits(v)) + } + return b, nil +} +func appendFixed64Value(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + v := *ptr.toUint64() + b = appendVarint(b, wiretag) + b = appendFixed64(b, v) + return b, nil +} +func appendFixed64ValueNoZero(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + v := *ptr.toUint64() + if v == 0 { + return b, nil + } + b = appendVarint(b, wiretag) + b = appendFixed64(b, v) + return b, nil +} +func appendFixed64Ptr(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + p := *ptr.toUint64Ptr() + if p == nil { + return b, nil + } + b = appendVarint(b, wiretag) + b = appendFixed64(b, *p) + return b, nil +} +func appendFixed64Slice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + s := *ptr.toUint64Slice() + for _, v := range s { + b = appendVarint(b, wiretag) + b = appendFixed64(b, v) + } + return b, nil +} +func appendFixed64PackedSlice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + s := *ptr.toUint64Slice() + if len(s) == 0 { + return b, nil + } + b = appendVarint(b, wiretag&^7|WireBytes) + b = appendVarint(b, uint64(8*len(s))) + for _, v := range s { + b = appendFixed64(b, v) + } + return b, nil +} +func appendFixedS64Value(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + v := *ptr.toInt64() + b = appendVarint(b, wiretag) + b = appendFixed64(b, uint64(v)) + return b, nil +} +func appendFixedS64ValueNoZero(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + v := *ptr.toInt64() + if v == 0 { + return b, nil + } + b = appendVarint(b, wiretag) + b = appendFixed64(b, uint64(v)) + return b, nil +} +func appendFixedS64Ptr(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + p := *ptr.toInt64Ptr() + if p == nil { + return b, nil + } + b = appendVarint(b, wiretag) + b = appendFixed64(b, uint64(*p)) + return b, nil +} +func appendFixedS64Slice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + s := *ptr.toInt64Slice() + for _, v := range s { + b = appendVarint(b, wiretag) + b = appendFixed64(b, uint64(v)) + } + return b, nil +} +func appendFixedS64PackedSlice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + s := *ptr.toInt64Slice() + if len(s) == 0 { + return b, nil + } + b = appendVarint(b, wiretag&^7|WireBytes) + b = appendVarint(b, uint64(8*len(s))) + for _, v := range s { + b = appendFixed64(b, uint64(v)) + } + return b, nil +} +func appendFloat64Value(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + v := math.Float64bits(*ptr.toFloat64()) + b = appendVarint(b, wiretag) + b = appendFixed64(b, v) + return b, nil +} +func appendFloat64ValueNoZero(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + v := math.Float64bits(*ptr.toFloat64()) + if v == 0 { + return b, nil + } + b = appendVarint(b, wiretag) + b = appendFixed64(b, v) + return b, nil +} +func appendFloat64Ptr(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + p := *ptr.toFloat64Ptr() + if p == nil { + return b, nil + } + b = appendVarint(b, wiretag) + b = appendFixed64(b, math.Float64bits(*p)) + return b, nil +} +func appendFloat64Slice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + s := *ptr.toFloat64Slice() + for _, v := range s { + b = appendVarint(b, wiretag) + b = appendFixed64(b, math.Float64bits(v)) + } + return b, nil +} +func appendFloat64PackedSlice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + s := *ptr.toFloat64Slice() + if len(s) == 0 { + return b, nil + } + b = appendVarint(b, wiretag&^7|WireBytes) + b = appendVarint(b, uint64(8*len(s))) + for _, v := range s { + b = appendFixed64(b, math.Float64bits(v)) + } + return b, nil +} +func appendVarint32Value(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + v := *ptr.toUint32() + b = appendVarint(b, wiretag) + b = appendVarint(b, uint64(v)) + return b, nil +} +func appendVarint32ValueNoZero(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + v := *ptr.toUint32() + if v == 0 { + return b, nil + } + b = appendVarint(b, wiretag) + b = appendVarint(b, uint64(v)) + return b, nil +} +func appendVarint32Ptr(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + p := *ptr.toUint32Ptr() + if p == nil { + return b, nil + } + b = appendVarint(b, wiretag) + b = appendVarint(b, uint64(*p)) + return b, nil +} +func appendVarint32Slice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + s := *ptr.toUint32Slice() + for _, v := range s { + b = appendVarint(b, wiretag) + b = appendVarint(b, uint64(v)) + } + return b, nil +} +func appendVarint32PackedSlice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + s := *ptr.toUint32Slice() + if len(s) == 0 { + return b, nil + } + b = appendVarint(b, wiretag&^7|WireBytes) + // compute size + n := 0 + for _, v := range s { + n += SizeVarint(uint64(v)) + } + b = appendVarint(b, uint64(n)) + for _, v := range s { + b = appendVarint(b, uint64(v)) + } + return b, nil +} +func appendVarintS32Value(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + v := *ptr.toInt32() + b = appendVarint(b, wiretag) + b = appendVarint(b, uint64(v)) + return b, nil +} +func appendVarintS32ValueNoZero(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + v := *ptr.toInt32() + if v == 0 { + return b, nil + } + b = appendVarint(b, wiretag) + b = appendVarint(b, uint64(v)) + return b, nil +} +func appendVarintS32Ptr(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + p := ptr.getInt32Ptr() + if p == nil { + return b, nil + } + b = appendVarint(b, wiretag) + b = appendVarint(b, uint64(*p)) + return b, nil +} +func appendVarintS32Slice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + s := ptr.getInt32Slice() + for _, v := range s { + b = appendVarint(b, wiretag) + b = appendVarint(b, uint64(v)) + } + return b, nil +} +func appendVarintS32PackedSlice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + s := ptr.getInt32Slice() + if len(s) == 0 { + return b, nil + } + b = appendVarint(b, wiretag&^7|WireBytes) + // compute size + n := 0 + for _, v := range s { + n += SizeVarint(uint64(v)) + } + b = appendVarint(b, uint64(n)) + for _, v := range s { + b = appendVarint(b, uint64(v)) + } + return b, nil +} +func appendVarint64Value(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + v := *ptr.toUint64() + b = appendVarint(b, wiretag) + b = appendVarint(b, v) + return b, nil +} +func appendVarint64ValueNoZero(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + v := *ptr.toUint64() + if v == 0 { + return b, nil + } + b = appendVarint(b, wiretag) + b = appendVarint(b, v) + return b, nil +} +func appendVarint64Ptr(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + p := *ptr.toUint64Ptr() + if p == nil { + return b, nil + } + b = appendVarint(b, wiretag) + b = appendVarint(b, *p) + return b, nil +} +func appendVarint64Slice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + s := *ptr.toUint64Slice() + for _, v := range s { + b = appendVarint(b, wiretag) + b = appendVarint(b, v) + } + return b, nil +} +func appendVarint64PackedSlice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + s := *ptr.toUint64Slice() + if len(s) == 0 { + return b, nil + } + b = appendVarint(b, wiretag&^7|WireBytes) + // compute size + n := 0 + for _, v := range s { + n += SizeVarint(v) + } + b = appendVarint(b, uint64(n)) + for _, v := range s { + b = appendVarint(b, v) + } + return b, nil +} +func appendVarintS64Value(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + v := *ptr.toInt64() + b = appendVarint(b, wiretag) + b = appendVarint(b, uint64(v)) + return b, nil +} +func appendVarintS64ValueNoZero(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + v := *ptr.toInt64() + if v == 0 { + return b, nil + } + b = appendVarint(b, wiretag) + b = appendVarint(b, uint64(v)) + return b, nil +} +func appendVarintS64Ptr(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + p := *ptr.toInt64Ptr() + if p == nil { + return b, nil + } + b = appendVarint(b, wiretag) + b = appendVarint(b, uint64(*p)) + return b, nil +} +func appendVarintS64Slice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + s := *ptr.toInt64Slice() + for _, v := range s { + b = appendVarint(b, wiretag) + b = appendVarint(b, uint64(v)) + } + return b, nil +} +func appendVarintS64PackedSlice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + s := *ptr.toInt64Slice() + if len(s) == 0 { + return b, nil + } + b = appendVarint(b, wiretag&^7|WireBytes) + // compute size + n := 0 + for _, v := range s { + n += SizeVarint(uint64(v)) + } + b = appendVarint(b, uint64(n)) + for _, v := range s { + b = appendVarint(b, uint64(v)) + } + return b, nil +} +func appendZigzag32Value(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + v := *ptr.toInt32() + b = appendVarint(b, wiretag) + b = appendVarint(b, uint64((uint32(v)<<1)^uint32((int32(v)>>31)))) + return b, nil +} +func appendZigzag32ValueNoZero(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + v := *ptr.toInt32() + if v == 0 { + return b, nil + } + b = appendVarint(b, wiretag) + b = appendVarint(b, uint64((uint32(v)<<1)^uint32((int32(v)>>31)))) + return b, nil +} +func appendZigzag32Ptr(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + p := ptr.getInt32Ptr() + if p == nil { + return b, nil + } + b = appendVarint(b, wiretag) + v := *p + b = appendVarint(b, uint64((uint32(v)<<1)^uint32((int32(v)>>31)))) + return b, nil +} +func appendZigzag32Slice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + s := ptr.getInt32Slice() + for _, v := range s { + b = appendVarint(b, wiretag) + b = appendVarint(b, uint64((uint32(v)<<1)^uint32((int32(v)>>31)))) + } + return b, nil +} +func appendZigzag32PackedSlice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + s := ptr.getInt32Slice() + if len(s) == 0 { + return b, nil + } + b = appendVarint(b, wiretag&^7|WireBytes) + // compute size + n := 0 + for _, v := range s { + n += SizeVarint(uint64((uint32(v) << 1) ^ uint32((int32(v) >> 31)))) + } + b = appendVarint(b, uint64(n)) + for _, v := range s { + b = appendVarint(b, uint64((uint32(v)<<1)^uint32((int32(v)>>31)))) + } + return b, nil +} +func appendZigzag64Value(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + v := *ptr.toInt64() + b = appendVarint(b, wiretag) + b = appendVarint(b, uint64(v<<1)^uint64((int64(v)>>63))) + return b, nil +} +func appendZigzag64ValueNoZero(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + v := *ptr.toInt64() + if v == 0 { + return b, nil + } + b = appendVarint(b, wiretag) + b = appendVarint(b, uint64(v<<1)^uint64((int64(v)>>63))) + return b, nil +} +func appendZigzag64Ptr(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + p := *ptr.toInt64Ptr() + if p == nil { + return b, nil + } + b = appendVarint(b, wiretag) + v := *p + b = appendVarint(b, uint64(v<<1)^uint64((int64(v)>>63))) + return b, nil +} +func appendZigzag64Slice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + s := *ptr.toInt64Slice() + for _, v := range s { + b = appendVarint(b, wiretag) + b = appendVarint(b, uint64(v<<1)^uint64((int64(v)>>63))) + } + return b, nil +} +func appendZigzag64PackedSlice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + s := *ptr.toInt64Slice() + if len(s) == 0 { + return b, nil + } + b = appendVarint(b, wiretag&^7|WireBytes) + // compute size + n := 0 + for _, v := range s { + n += SizeVarint(uint64(v<<1) ^ uint64((int64(v) >> 63))) + } + b = appendVarint(b, uint64(n)) + for _, v := range s { + b = appendVarint(b, uint64(v<<1)^uint64((int64(v)>>63))) + } + return b, nil +} +func appendBoolValue(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + v := *ptr.toBool() + b = appendVarint(b, wiretag) + if v { + b = append(b, 1) + } else { + b = append(b, 0) + } + return b, nil +} +func appendBoolValueNoZero(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + v := *ptr.toBool() + if !v { + return b, nil + } + b = appendVarint(b, wiretag) + b = append(b, 1) + return b, nil +} + +func appendBoolPtr(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + p := *ptr.toBoolPtr() + if p == nil { + return b, nil + } + b = appendVarint(b, wiretag) + if *p { + b = append(b, 1) + } else { + b = append(b, 0) + } + return b, nil +} +func appendBoolSlice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + s := *ptr.toBoolSlice() + for _, v := range s { + b = appendVarint(b, wiretag) + if v { + b = append(b, 1) + } else { + b = append(b, 0) + } + } + return b, nil +} +func appendBoolPackedSlice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + s := *ptr.toBoolSlice() + if len(s) == 0 { + return b, nil + } + b = appendVarint(b, wiretag&^7|WireBytes) + b = appendVarint(b, uint64(len(s))) + for _, v := range s { + if v { + b = append(b, 1) + } else { + b = append(b, 0) + } + } + return b, nil +} +func appendStringValue(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + v := *ptr.toString() + b = appendVarint(b, wiretag) + b = appendVarint(b, uint64(len(v))) + b = append(b, v...) + return b, nil +} +func appendStringValueNoZero(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + v := *ptr.toString() + if v == "" { + return b, nil + } + b = appendVarint(b, wiretag) + b = appendVarint(b, uint64(len(v))) + b = append(b, v...) + return b, nil +} +func appendStringPtr(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + p := *ptr.toStringPtr() + if p == nil { + return b, nil + } + v := *p + b = appendVarint(b, wiretag) + b = appendVarint(b, uint64(len(v))) + b = append(b, v...) + return b, nil +} +func appendStringSlice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + s := *ptr.toStringSlice() + for _, v := range s { + b = appendVarint(b, wiretag) + b = appendVarint(b, uint64(len(v))) + b = append(b, v...) + } + return b, nil +} +func appendUTF8StringValue(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + var invalidUTF8 bool + v := *ptr.toString() + if !utf8.ValidString(v) { + invalidUTF8 = true + } + b = appendVarint(b, wiretag) + b = appendVarint(b, uint64(len(v))) + b = append(b, v...) + if invalidUTF8 { + return b, errInvalidUTF8 + } + return b, nil +} +func appendUTF8StringValueNoZero(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + var invalidUTF8 bool + v := *ptr.toString() + if v == "" { + return b, nil + } + if !utf8.ValidString(v) { + invalidUTF8 = true + } + b = appendVarint(b, wiretag) + b = appendVarint(b, uint64(len(v))) + b = append(b, v...) + if invalidUTF8 { + return b, errInvalidUTF8 + } + return b, nil +} +func appendUTF8StringPtr(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + var invalidUTF8 bool + p := *ptr.toStringPtr() + if p == nil { + return b, nil + } + v := *p + if !utf8.ValidString(v) { + invalidUTF8 = true + } + b = appendVarint(b, wiretag) + b = appendVarint(b, uint64(len(v))) + b = append(b, v...) + if invalidUTF8 { + return b, errInvalidUTF8 + } + return b, nil +} +func appendUTF8StringSlice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + var invalidUTF8 bool + s := *ptr.toStringSlice() + for _, v := range s { + if !utf8.ValidString(v) { + invalidUTF8 = true + } + b = appendVarint(b, wiretag) + b = appendVarint(b, uint64(len(v))) + b = append(b, v...) + } + if invalidUTF8 { + return b, errInvalidUTF8 + } + return b, nil +} +func appendBytes(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + v := *ptr.toBytes() + if v == nil { + return b, nil + } + b = appendVarint(b, wiretag) + b = appendVarint(b, uint64(len(v))) + b = append(b, v...) + return b, nil +} +func appendBytes3(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + v := *ptr.toBytes() + if len(v) == 0 { + return b, nil + } + b = appendVarint(b, wiretag) + b = appendVarint(b, uint64(len(v))) + b = append(b, v...) + return b, nil +} +func appendBytesOneof(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + v := *ptr.toBytes() + b = appendVarint(b, wiretag) + b = appendVarint(b, uint64(len(v))) + b = append(b, v...) + return b, nil +} +func appendBytesSlice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + s := *ptr.toBytesSlice() + for _, v := range s { + b = appendVarint(b, wiretag) + b = appendVarint(b, uint64(len(v))) + b = append(b, v...) + } + return b, nil +} + +// makeGroupMarshaler returns the sizer and marshaler for a group. +// u is the marshal info of the underlying message. +func makeGroupMarshaler(u *marshalInfo) (sizer, marshaler) { + return func(ptr pointer, tagsize int) int { + p := ptr.getPointer() + if p.isNil() { + return 0 + } + return u.size(p) + 2*tagsize + }, + func(b []byte, ptr pointer, wiretag uint64, deterministic bool) ([]byte, error) { + p := ptr.getPointer() + if p.isNil() { + return b, nil + } + var err error + b = appendVarint(b, wiretag) // start group + b, err = u.marshal(b, p, deterministic) + b = appendVarint(b, wiretag+(WireEndGroup-WireStartGroup)) // end group + return b, err + } +} + +// makeGroupSliceMarshaler returns the sizer and marshaler for a group slice. +// u is the marshal info of the underlying message. +func makeGroupSliceMarshaler(u *marshalInfo) (sizer, marshaler) { + return func(ptr pointer, tagsize int) int { + s := ptr.getPointerSlice() + n := 0 + for _, v := range s { + if v.isNil() { + continue + } + n += u.size(v) + 2*tagsize + } + return n + }, + func(b []byte, ptr pointer, wiretag uint64, deterministic bool) ([]byte, error) { + s := ptr.getPointerSlice() + var err error + var nerr nonFatal + for _, v := range s { + if v.isNil() { + return b, errRepeatedHasNil + } + b = appendVarint(b, wiretag) // start group + b, err = u.marshal(b, v, deterministic) + b = appendVarint(b, wiretag+(WireEndGroup-WireStartGroup)) // end group + if !nerr.Merge(err) { + if err == ErrNil { + err = errRepeatedHasNil + } + return b, err + } + } + return b, nerr.E + } +} + +// makeMessageMarshaler returns the sizer and marshaler for a message field. +// u is the marshal info of the message. +func makeMessageMarshaler(u *marshalInfo) (sizer, marshaler) { + return func(ptr pointer, tagsize int) int { + p := ptr.getPointer() + if p.isNil() { + return 0 + } + siz := u.size(p) + return siz + SizeVarint(uint64(siz)) + tagsize + }, + func(b []byte, ptr pointer, wiretag uint64, deterministic bool) ([]byte, error) { + p := ptr.getPointer() + if p.isNil() { + return b, nil + } + b = appendVarint(b, wiretag) + siz := u.cachedsize(p) + b = appendVarint(b, uint64(siz)) + return u.marshal(b, p, deterministic) + } +} + +// makeMessageSliceMarshaler returns the sizer and marshaler for a message slice. +// u is the marshal info of the message. +func makeMessageSliceMarshaler(u *marshalInfo) (sizer, marshaler) { + return func(ptr pointer, tagsize int) int { + s := ptr.getPointerSlice() + n := 0 + for _, v := range s { + if v.isNil() { + continue + } + siz := u.size(v) + n += siz + SizeVarint(uint64(siz)) + tagsize + } + return n + }, + func(b []byte, ptr pointer, wiretag uint64, deterministic bool) ([]byte, error) { + s := ptr.getPointerSlice() + var err error + var nerr nonFatal + for _, v := range s { + if v.isNil() { + return b, errRepeatedHasNil + } + b = appendVarint(b, wiretag) + siz := u.cachedsize(v) + b = appendVarint(b, uint64(siz)) + b, err = u.marshal(b, v, deterministic) + + if !nerr.Merge(err) { + if err == ErrNil { + err = errRepeatedHasNil + } + return b, err + } + } + return b, nerr.E + } +} + +// makeMapMarshaler returns the sizer and marshaler for a map field. +// f is the pointer to the reflect data structure of the field. +func makeMapMarshaler(f *reflect.StructField) (sizer, marshaler) { + // figure out key and value type + t := f.Type + keyType := t.Key() + valType := t.Elem() + keyTags := strings.Split(f.Tag.Get("protobuf_key"), ",") + valTags := strings.Split(f.Tag.Get("protobuf_val"), ",") + keySizer, keyMarshaler := typeMarshaler(keyType, keyTags, false, false) // don't omit zero value in map + valSizer, valMarshaler := typeMarshaler(valType, valTags, false, false) // don't omit zero value in map + keyWireTag := 1<<3 | wiretype(keyTags[0]) + valWireTag := 2<<3 | wiretype(valTags[0]) + + // We create an interface to get the addresses of the map key and value. + // If value is pointer-typed, the interface is a direct interface, the + // idata itself is the value. Otherwise, the idata is the pointer to the + // value. + // Key cannot be pointer-typed. + valIsPtr := valType.Kind() == reflect.Ptr + + // If value is a message with nested maps, calling + // valSizer in marshal may be quadratic. We should use + // cached version in marshal (but not in size). + // If value is not message type, we don't have size cache, + // but it cannot be nested either. Just use valSizer. + valCachedSizer := valSizer + if valIsPtr && valType.Elem().Kind() == reflect.Struct { + u := getMarshalInfo(valType.Elem()) + valCachedSizer = func(ptr pointer, tagsize int) int { + // Same as message sizer, but use cache. + p := ptr.getPointer() + if p.isNil() { + return 0 + } + siz := u.cachedsize(p) + return siz + SizeVarint(uint64(siz)) + tagsize + } + } + return func(ptr pointer, tagsize int) int { + m := ptr.asPointerTo(t).Elem() // the map + n := 0 + for _, k := range m.MapKeys() { + ki := k.Interface() + vi := m.MapIndex(k).Interface() + kaddr := toAddrPointer(&ki, false) // pointer to key + vaddr := toAddrPointer(&vi, valIsPtr) // pointer to value + siz := keySizer(kaddr, 1) + valSizer(vaddr, 1) // tag of key = 1 (size=1), tag of val = 2 (size=1) + n += siz + SizeVarint(uint64(siz)) + tagsize + } + return n + }, + func(b []byte, ptr pointer, tag uint64, deterministic bool) ([]byte, error) { + m := ptr.asPointerTo(t).Elem() // the map + var err error + keys := m.MapKeys() + if len(keys) > 1 && deterministic { + sort.Sort(mapKeys(keys)) + } + + var nerr nonFatal + for _, k := range keys { + ki := k.Interface() + vi := m.MapIndex(k).Interface() + kaddr := toAddrPointer(&ki, false) // pointer to key + vaddr := toAddrPointer(&vi, valIsPtr) // pointer to value + b = appendVarint(b, tag) + siz := keySizer(kaddr, 1) + valCachedSizer(vaddr, 1) // tag of key = 1 (size=1), tag of val = 2 (size=1) + b = appendVarint(b, uint64(siz)) + b, err = keyMarshaler(b, kaddr, keyWireTag, deterministic) + if !nerr.Merge(err) { + return b, err + } + b, err = valMarshaler(b, vaddr, valWireTag, deterministic) + if err != ErrNil && !nerr.Merge(err) { // allow nil value in map + return b, err + } + } + return b, nerr.E + } +} + +// makeOneOfMarshaler returns the sizer and marshaler for a oneof field. +// fi is the marshal info of the field. +// f is the pointer to the reflect data structure of the field. +func makeOneOfMarshaler(fi *marshalFieldInfo, f *reflect.StructField) (sizer, marshaler) { + // Oneof field is an interface. We need to get the actual data type on the fly. + t := f.Type + return func(ptr pointer, _ int) int { + p := ptr.getInterfacePointer() + if p.isNil() { + return 0 + } + v := ptr.asPointerTo(t).Elem().Elem().Elem() // *interface -> interface -> *struct -> struct + telem := v.Type() + e := fi.oneofElems[telem] + return e.sizer(p, e.tagsize) + }, + func(b []byte, ptr pointer, _ uint64, deterministic bool) ([]byte, error) { + p := ptr.getInterfacePointer() + if p.isNil() { + return b, nil + } + v := ptr.asPointerTo(t).Elem().Elem().Elem() // *interface -> interface -> *struct -> struct + telem := v.Type() + if telem.Field(0).Type.Kind() == reflect.Ptr && p.getPointer().isNil() { + return b, errOneofHasNil + } + e := fi.oneofElems[telem] + return e.marshaler(b, p, e.wiretag, deterministic) + } +} + +// sizeExtensions computes the size of encoded data for a XXX_InternalExtensions field. +func (u *marshalInfo) sizeExtensions(ext *XXX_InternalExtensions) int { + m, mu := ext.extensionsRead() + if m == nil { + return 0 + } + mu.Lock() + + n := 0 + for _, e := range m { + if e.value == nil || e.desc == nil { + // Extension is only in its encoded form. + n += len(e.enc) + continue + } + + // We don't skip extensions that have an encoded form set, + // because the extension value may have been mutated after + // the last time this function was called. + ei := u.getExtElemInfo(e.desc) + v := e.value + p := toAddrPointer(&v, ei.isptr) + n += ei.sizer(p, ei.tagsize) + } + mu.Unlock() + return n +} + +// appendExtensions marshals a XXX_InternalExtensions field to the end of byte slice b. +func (u *marshalInfo) appendExtensions(b []byte, ext *XXX_InternalExtensions, deterministic bool) ([]byte, error) { + m, mu := ext.extensionsRead() + if m == nil { + return b, nil + } + mu.Lock() + defer mu.Unlock() + + var err error + var nerr nonFatal + + // Fast-path for common cases: zero or one extensions. + // Don't bother sorting the keys. + if len(m) <= 1 { + for _, e := range m { + if e.value == nil || e.desc == nil { + // Extension is only in its encoded form. + b = append(b, e.enc...) + continue + } + + // We don't skip extensions that have an encoded form set, + // because the extension value may have been mutated after + // the last time this function was called. + + ei := u.getExtElemInfo(e.desc) + v := e.value + p := toAddrPointer(&v, ei.isptr) + b, err = ei.marshaler(b, p, ei.wiretag, deterministic) + if !nerr.Merge(err) { + return b, err + } + } + return b, nerr.E + } + + // Sort the keys to provide a deterministic encoding. + // Not sure this is required, but the old code does it. + keys := make([]int, 0, len(m)) + for k := range m { + keys = append(keys, int(k)) + } + sort.Ints(keys) + + for _, k := range keys { + e := m[int32(k)] + if e.value == nil || e.desc == nil { + // Extension is only in its encoded form. + b = append(b, e.enc...) + continue + } + + // We don't skip extensions that have an encoded form set, + // because the extension value may have been mutated after + // the last time this function was called. + + ei := u.getExtElemInfo(e.desc) + v := e.value + p := toAddrPointer(&v, ei.isptr) + b, err = ei.marshaler(b, p, ei.wiretag, deterministic) + if !nerr.Merge(err) { + return b, err + } + } + return b, nerr.E +} + +// message set format is: +// message MessageSet { +// repeated group Item = 1 { +// required int32 type_id = 2; +// required string message = 3; +// }; +// } + +// sizeMessageSet computes the size of encoded data for a XXX_InternalExtensions field +// in message set format (above). +func (u *marshalInfo) sizeMessageSet(ext *XXX_InternalExtensions) int { + m, mu := ext.extensionsRead() + if m == nil { + return 0 + } + mu.Lock() + + n := 0 + for id, e := range m { + n += 2 // start group, end group. tag = 1 (size=1) + n += SizeVarint(uint64(id)) + 1 // type_id, tag = 2 (size=1) + + if e.value == nil || e.desc == nil { + // Extension is only in its encoded form. + msgWithLen := skipVarint(e.enc) // skip old tag, but leave the length varint + siz := len(msgWithLen) + n += siz + 1 // message, tag = 3 (size=1) + continue + } + + // We don't skip extensions that have an encoded form set, + // because the extension value may have been mutated after + // the last time this function was called. + + ei := u.getExtElemInfo(e.desc) + v := e.value + p := toAddrPointer(&v, ei.isptr) + n += ei.sizer(p, 1) // message, tag = 3 (size=1) + } + mu.Unlock() + return n +} + +// appendMessageSet marshals a XXX_InternalExtensions field in message set format (above) +// to the end of byte slice b. +func (u *marshalInfo) appendMessageSet(b []byte, ext *XXX_InternalExtensions, deterministic bool) ([]byte, error) { + m, mu := ext.extensionsRead() + if m == nil { + return b, nil + } + mu.Lock() + defer mu.Unlock() + + var err error + var nerr nonFatal + + // Fast-path for common cases: zero or one extensions. + // Don't bother sorting the keys. + if len(m) <= 1 { + for id, e := range m { + b = append(b, 1<<3|WireStartGroup) + b = append(b, 2<<3|WireVarint) + b = appendVarint(b, uint64(id)) + + if e.value == nil || e.desc == nil { + // Extension is only in its encoded form. + msgWithLen := skipVarint(e.enc) // skip old tag, but leave the length varint + b = append(b, 3<<3|WireBytes) + b = append(b, msgWithLen...) + b = append(b, 1<<3|WireEndGroup) + continue + } + + // We don't skip extensions that have an encoded form set, + // because the extension value may have been mutated after + // the last time this function was called. + + ei := u.getExtElemInfo(e.desc) + v := e.value + p := toAddrPointer(&v, ei.isptr) + b, err = ei.marshaler(b, p, 3<<3|WireBytes, deterministic) + if !nerr.Merge(err) { + return b, err + } + b = append(b, 1<<3|WireEndGroup) + } + return b, nerr.E + } + + // Sort the keys to provide a deterministic encoding. + keys := make([]int, 0, len(m)) + for k := range m { + keys = append(keys, int(k)) + } + sort.Ints(keys) + + for _, id := range keys { + e := m[int32(id)] + b = append(b, 1<<3|WireStartGroup) + b = append(b, 2<<3|WireVarint) + b = appendVarint(b, uint64(id)) + + if e.value == nil || e.desc == nil { + // Extension is only in its encoded form. + msgWithLen := skipVarint(e.enc) // skip old tag, but leave the length varint + b = append(b, 3<<3|WireBytes) + b = append(b, msgWithLen...) + b = append(b, 1<<3|WireEndGroup) + continue + } + + // We don't skip extensions that have an encoded form set, + // because the extension value may have been mutated after + // the last time this function was called. + + ei := u.getExtElemInfo(e.desc) + v := e.value + p := toAddrPointer(&v, ei.isptr) + b, err = ei.marshaler(b, p, 3<<3|WireBytes, deterministic) + b = append(b, 1<<3|WireEndGroup) + if !nerr.Merge(err) { + return b, err + } + } + return b, nerr.E +} + +// sizeV1Extensions computes the size of encoded data for a V1-API extension field. +func (u *marshalInfo) sizeV1Extensions(m map[int32]Extension) int { + if m == nil { + return 0 + } + + n := 0 + for _, e := range m { + if e.value == nil || e.desc == nil { + // Extension is only in its encoded form. + n += len(e.enc) + continue + } + + // We don't skip extensions that have an encoded form set, + // because the extension value may have been mutated after + // the last time this function was called. + + ei := u.getExtElemInfo(e.desc) + v := e.value + p := toAddrPointer(&v, ei.isptr) + n += ei.sizer(p, ei.tagsize) + } + return n +} + +// appendV1Extensions marshals a V1-API extension field to the end of byte slice b. +func (u *marshalInfo) appendV1Extensions(b []byte, m map[int32]Extension, deterministic bool) ([]byte, error) { + if m == nil { + return b, nil + } + + // Sort the keys to provide a deterministic encoding. + keys := make([]int, 0, len(m)) + for k := range m { + keys = append(keys, int(k)) + } + sort.Ints(keys) + + var err error + var nerr nonFatal + for _, k := range keys { + e := m[int32(k)] + if e.value == nil || e.desc == nil { + // Extension is only in its encoded form. + b = append(b, e.enc...) + continue + } + + // We don't skip extensions that have an encoded form set, + // because the extension value may have been mutated after + // the last time this function was called. + + ei := u.getExtElemInfo(e.desc) + v := e.value + p := toAddrPointer(&v, ei.isptr) + b, err = ei.marshaler(b, p, ei.wiretag, deterministic) + if !nerr.Merge(err) { + return b, err + } + } + return b, nerr.E +} + +// newMarshaler is the interface representing objects that can marshal themselves. +// +// This exists to support protoc-gen-go generated messages. +// The proto package will stop type-asserting to this interface in the future. +// +// DO NOT DEPEND ON THIS. +type newMarshaler interface { + XXX_Size() int + XXX_Marshal(b []byte, deterministic bool) ([]byte, error) +} + +// Size returns the encoded size of a protocol buffer message. +// This is the main entry point. +func Size(pb Message) int { + if m, ok := pb.(newMarshaler); ok { + return m.XXX_Size() + } + if m, ok := pb.(Marshaler); ok { + // If the message can marshal itself, let it do it, for compatibility. + // NOTE: This is not efficient. + b, _ := m.Marshal() + return len(b) + } + // in case somehow we didn't generate the wrapper + if pb == nil { + return 0 + } + var info InternalMessageInfo + return info.Size(pb) +} + +// Marshal takes a protocol buffer message +// and encodes it into the wire format, returning the data. +// This is the main entry point. +func Marshal(pb Message) ([]byte, error) { + if m, ok := pb.(newMarshaler); ok { + siz := m.XXX_Size() + b := make([]byte, 0, siz) + return m.XXX_Marshal(b, false) + } + if m, ok := pb.(Marshaler); ok { + // If the message can marshal itself, let it do it, for compatibility. + // NOTE: This is not efficient. + return m.Marshal() + } + // in case somehow we didn't generate the wrapper + if pb == nil { + return nil, ErrNil + } + var info InternalMessageInfo + siz := info.Size(pb) + b := make([]byte, 0, siz) + return info.Marshal(b, pb, false) +} + +// Marshal takes a protocol buffer message +// and encodes it into the wire format, writing the result to the +// Buffer. +// This is an alternative entry point. It is not necessary to use +// a Buffer for most applications. +func (p *Buffer) Marshal(pb Message) error { + var err error + if m, ok := pb.(newMarshaler); ok { + siz := m.XXX_Size() + p.grow(siz) // make sure buf has enough capacity + p.buf, err = m.XXX_Marshal(p.buf, p.deterministic) + return err + } + if m, ok := pb.(Marshaler); ok { + // If the message can marshal itself, let it do it, for compatibility. + // NOTE: This is not efficient. + b, err := m.Marshal() + p.buf = append(p.buf, b...) + return err + } + // in case somehow we didn't generate the wrapper + if pb == nil { + return ErrNil + } + var info InternalMessageInfo + siz := info.Size(pb) + p.grow(siz) // make sure buf has enough capacity + p.buf, err = info.Marshal(p.buf, pb, p.deterministic) + return err +} + +// grow grows the buffer's capacity, if necessary, to guarantee space for +// another n bytes. After grow(n), at least n bytes can be written to the +// buffer without another allocation. +func (p *Buffer) grow(n int) { + need := len(p.buf) + n + if need <= cap(p.buf) { + return + } + newCap := len(p.buf) * 2 + if newCap < need { + newCap = need + } + p.buf = append(make([]byte, 0, newCap), p.buf...) +} diff --git a/chaincode/abac/go/vendor/github.com/golang/protobuf/proto/table_merge.go b/chaincode/abac/go/vendor/github.com/golang/protobuf/proto/table_merge.go new file mode 100644 index 00000000..5525def6 --- /dev/null +++ b/chaincode/abac/go/vendor/github.com/golang/protobuf/proto/table_merge.go @@ -0,0 +1,654 @@ +// Go support for Protocol Buffers - Google's data interchange format +// +// Copyright 2016 The Go Authors. All rights reserved. +// https://github.com/golang/protobuf +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +package proto + +import ( + "fmt" + "reflect" + "strings" + "sync" + "sync/atomic" +) + +// Merge merges the src message into dst. +// This assumes that dst and src of the same type and are non-nil. +func (a *InternalMessageInfo) Merge(dst, src Message) { + mi := atomicLoadMergeInfo(&a.merge) + if mi == nil { + mi = getMergeInfo(reflect.TypeOf(dst).Elem()) + atomicStoreMergeInfo(&a.merge, mi) + } + mi.merge(toPointer(&dst), toPointer(&src)) +} + +type mergeInfo struct { + typ reflect.Type + + initialized int32 // 0: only typ is valid, 1: everything is valid + lock sync.Mutex + + fields []mergeFieldInfo + unrecognized field // Offset of XXX_unrecognized +} + +type mergeFieldInfo struct { + field field // Offset of field, guaranteed to be valid + + // isPointer reports whether the value in the field is a pointer. + // This is true for the following situations: + // * Pointer to struct + // * Pointer to basic type (proto2 only) + // * Slice (first value in slice header is a pointer) + // * String (first value in string header is a pointer) + isPointer bool + + // basicWidth reports the width of the field assuming that it is directly + // embedded in the struct (as is the case for basic types in proto3). + // The possible values are: + // 0: invalid + // 1: bool + // 4: int32, uint32, float32 + // 8: int64, uint64, float64 + basicWidth int + + // Where dst and src are pointers to the types being merged. + merge func(dst, src pointer) +} + +var ( + mergeInfoMap = map[reflect.Type]*mergeInfo{} + mergeInfoLock sync.Mutex +) + +func getMergeInfo(t reflect.Type) *mergeInfo { + mergeInfoLock.Lock() + defer mergeInfoLock.Unlock() + mi := mergeInfoMap[t] + if mi == nil { + mi = &mergeInfo{typ: t} + mergeInfoMap[t] = mi + } + return mi +} + +// merge merges src into dst assuming they are both of type *mi.typ. +func (mi *mergeInfo) merge(dst, src pointer) { + if dst.isNil() { + panic("proto: nil destination") + } + if src.isNil() { + return // Nothing to do. + } + + if atomic.LoadInt32(&mi.initialized) == 0 { + mi.computeMergeInfo() + } + + for _, fi := range mi.fields { + sfp := src.offset(fi.field) + + // As an optimization, we can avoid the merge function call cost + // if we know for sure that the source will have no effect + // by checking if it is the zero value. + if unsafeAllowed { + if fi.isPointer && sfp.getPointer().isNil() { // Could be slice or string + continue + } + if fi.basicWidth > 0 { + switch { + case fi.basicWidth == 1 && !*sfp.toBool(): + continue + case fi.basicWidth == 4 && *sfp.toUint32() == 0: + continue + case fi.basicWidth == 8 && *sfp.toUint64() == 0: + continue + } + } + } + + dfp := dst.offset(fi.field) + fi.merge(dfp, sfp) + } + + // TODO: Make this faster? + out := dst.asPointerTo(mi.typ).Elem() + in := src.asPointerTo(mi.typ).Elem() + if emIn, err := extendable(in.Addr().Interface()); err == nil { + emOut, _ := extendable(out.Addr().Interface()) + mIn, muIn := emIn.extensionsRead() + if mIn != nil { + mOut := emOut.extensionsWrite() + muIn.Lock() + mergeExtension(mOut, mIn) + muIn.Unlock() + } + } + + if mi.unrecognized.IsValid() { + if b := *src.offset(mi.unrecognized).toBytes(); len(b) > 0 { + *dst.offset(mi.unrecognized).toBytes() = append([]byte(nil), b...) + } + } +} + +func (mi *mergeInfo) computeMergeInfo() { + mi.lock.Lock() + defer mi.lock.Unlock() + if mi.initialized != 0 { + return + } + t := mi.typ + n := t.NumField() + + props := GetProperties(t) + for i := 0; i < n; i++ { + f := t.Field(i) + if strings.HasPrefix(f.Name, "XXX_") { + continue + } + + mfi := mergeFieldInfo{field: toField(&f)} + tf := f.Type + + // As an optimization, we can avoid the merge function call cost + // if we know for sure that the source will have no effect + // by checking if it is the zero value. + if unsafeAllowed { + switch tf.Kind() { + case reflect.Ptr, reflect.Slice, reflect.String: + // As a special case, we assume slices and strings are pointers + // since we know that the first field in the SliceSlice or + // StringHeader is a data pointer. + mfi.isPointer = true + case reflect.Bool: + mfi.basicWidth = 1 + case reflect.Int32, reflect.Uint32, reflect.Float32: + mfi.basicWidth = 4 + case reflect.Int64, reflect.Uint64, reflect.Float64: + mfi.basicWidth = 8 + } + } + + // Unwrap tf to get at its most basic type. + var isPointer, isSlice bool + if tf.Kind() == reflect.Slice && tf.Elem().Kind() != reflect.Uint8 { + isSlice = true + tf = tf.Elem() + } + if tf.Kind() == reflect.Ptr { + isPointer = true + tf = tf.Elem() + } + if isPointer && isSlice && tf.Kind() != reflect.Struct { + panic("both pointer and slice for basic type in " + tf.Name()) + } + + switch tf.Kind() { + case reflect.Int32: + switch { + case isSlice: // E.g., []int32 + mfi.merge = func(dst, src pointer) { + // NOTE: toInt32Slice is not defined (see pointer_reflect.go). + /* + sfsp := src.toInt32Slice() + if *sfsp != nil { + dfsp := dst.toInt32Slice() + *dfsp = append(*dfsp, *sfsp...) + if *dfsp == nil { + *dfsp = []int64{} + } + } + */ + sfs := src.getInt32Slice() + if sfs != nil { + dfs := dst.getInt32Slice() + dfs = append(dfs, sfs...) + if dfs == nil { + dfs = []int32{} + } + dst.setInt32Slice(dfs) + } + } + case isPointer: // E.g., *int32 + mfi.merge = func(dst, src pointer) { + // NOTE: toInt32Ptr is not defined (see pointer_reflect.go). + /* + sfpp := src.toInt32Ptr() + if *sfpp != nil { + dfpp := dst.toInt32Ptr() + if *dfpp == nil { + *dfpp = Int32(**sfpp) + } else { + **dfpp = **sfpp + } + } + */ + sfp := src.getInt32Ptr() + if sfp != nil { + dfp := dst.getInt32Ptr() + if dfp == nil { + dst.setInt32Ptr(*sfp) + } else { + *dfp = *sfp + } + } + } + default: // E.g., int32 + mfi.merge = func(dst, src pointer) { + if v := *src.toInt32(); v != 0 { + *dst.toInt32() = v + } + } + } + case reflect.Int64: + switch { + case isSlice: // E.g., []int64 + mfi.merge = func(dst, src pointer) { + sfsp := src.toInt64Slice() + if *sfsp != nil { + dfsp := dst.toInt64Slice() + *dfsp = append(*dfsp, *sfsp...) + if *dfsp == nil { + *dfsp = []int64{} + } + } + } + case isPointer: // E.g., *int64 + mfi.merge = func(dst, src pointer) { + sfpp := src.toInt64Ptr() + if *sfpp != nil { + dfpp := dst.toInt64Ptr() + if *dfpp == nil { + *dfpp = Int64(**sfpp) + } else { + **dfpp = **sfpp + } + } + } + default: // E.g., int64 + mfi.merge = func(dst, src pointer) { + if v := *src.toInt64(); v != 0 { + *dst.toInt64() = v + } + } + } + case reflect.Uint32: + switch { + case isSlice: // E.g., []uint32 + mfi.merge = func(dst, src pointer) { + sfsp := src.toUint32Slice() + if *sfsp != nil { + dfsp := dst.toUint32Slice() + *dfsp = append(*dfsp, *sfsp...) + if *dfsp == nil { + *dfsp = []uint32{} + } + } + } + case isPointer: // E.g., *uint32 + mfi.merge = func(dst, src pointer) { + sfpp := src.toUint32Ptr() + if *sfpp != nil { + dfpp := dst.toUint32Ptr() + if *dfpp == nil { + *dfpp = Uint32(**sfpp) + } else { + **dfpp = **sfpp + } + } + } + default: // E.g., uint32 + mfi.merge = func(dst, src pointer) { + if v := *src.toUint32(); v != 0 { + *dst.toUint32() = v + } + } + } + case reflect.Uint64: + switch { + case isSlice: // E.g., []uint64 + mfi.merge = func(dst, src pointer) { + sfsp := src.toUint64Slice() + if *sfsp != nil { + dfsp := dst.toUint64Slice() + *dfsp = append(*dfsp, *sfsp...) + if *dfsp == nil { + *dfsp = []uint64{} + } + } + } + case isPointer: // E.g., *uint64 + mfi.merge = func(dst, src pointer) { + sfpp := src.toUint64Ptr() + if *sfpp != nil { + dfpp := dst.toUint64Ptr() + if *dfpp == nil { + *dfpp = Uint64(**sfpp) + } else { + **dfpp = **sfpp + } + } + } + default: // E.g., uint64 + mfi.merge = func(dst, src pointer) { + if v := *src.toUint64(); v != 0 { + *dst.toUint64() = v + } + } + } + case reflect.Float32: + switch { + case isSlice: // E.g., []float32 + mfi.merge = func(dst, src pointer) { + sfsp := src.toFloat32Slice() + if *sfsp != nil { + dfsp := dst.toFloat32Slice() + *dfsp = append(*dfsp, *sfsp...) + if *dfsp == nil { + *dfsp = []float32{} + } + } + } + case isPointer: // E.g., *float32 + mfi.merge = func(dst, src pointer) { + sfpp := src.toFloat32Ptr() + if *sfpp != nil { + dfpp := dst.toFloat32Ptr() + if *dfpp == nil { + *dfpp = Float32(**sfpp) + } else { + **dfpp = **sfpp + } + } + } + default: // E.g., float32 + mfi.merge = func(dst, src pointer) { + if v := *src.toFloat32(); v != 0 { + *dst.toFloat32() = v + } + } + } + case reflect.Float64: + switch { + case isSlice: // E.g., []float64 + mfi.merge = func(dst, src pointer) { + sfsp := src.toFloat64Slice() + if *sfsp != nil { + dfsp := dst.toFloat64Slice() + *dfsp = append(*dfsp, *sfsp...) + if *dfsp == nil { + *dfsp = []float64{} + } + } + } + case isPointer: // E.g., *float64 + mfi.merge = func(dst, src pointer) { + sfpp := src.toFloat64Ptr() + if *sfpp != nil { + dfpp := dst.toFloat64Ptr() + if *dfpp == nil { + *dfpp = Float64(**sfpp) + } else { + **dfpp = **sfpp + } + } + } + default: // E.g., float64 + mfi.merge = func(dst, src pointer) { + if v := *src.toFloat64(); v != 0 { + *dst.toFloat64() = v + } + } + } + case reflect.Bool: + switch { + case isSlice: // E.g., []bool + mfi.merge = func(dst, src pointer) { + sfsp := src.toBoolSlice() + if *sfsp != nil { + dfsp := dst.toBoolSlice() + *dfsp = append(*dfsp, *sfsp...) + if *dfsp == nil { + *dfsp = []bool{} + } + } + } + case isPointer: // E.g., *bool + mfi.merge = func(dst, src pointer) { + sfpp := src.toBoolPtr() + if *sfpp != nil { + dfpp := dst.toBoolPtr() + if *dfpp == nil { + *dfpp = Bool(**sfpp) + } else { + **dfpp = **sfpp + } + } + } + default: // E.g., bool + mfi.merge = func(dst, src pointer) { + if v := *src.toBool(); v { + *dst.toBool() = v + } + } + } + case reflect.String: + switch { + case isSlice: // E.g., []string + mfi.merge = func(dst, src pointer) { + sfsp := src.toStringSlice() + if *sfsp != nil { + dfsp := dst.toStringSlice() + *dfsp = append(*dfsp, *sfsp...) + if *dfsp == nil { + *dfsp = []string{} + } + } + } + case isPointer: // E.g., *string + mfi.merge = func(dst, src pointer) { + sfpp := src.toStringPtr() + if *sfpp != nil { + dfpp := dst.toStringPtr() + if *dfpp == nil { + *dfpp = String(**sfpp) + } else { + **dfpp = **sfpp + } + } + } + default: // E.g., string + mfi.merge = func(dst, src pointer) { + if v := *src.toString(); v != "" { + *dst.toString() = v + } + } + } + case reflect.Slice: + isProto3 := props.Prop[i].proto3 + switch { + case isPointer: + panic("bad pointer in byte slice case in " + tf.Name()) + case tf.Elem().Kind() != reflect.Uint8: + panic("bad element kind in byte slice case in " + tf.Name()) + case isSlice: // E.g., [][]byte + mfi.merge = func(dst, src pointer) { + sbsp := src.toBytesSlice() + if *sbsp != nil { + dbsp := dst.toBytesSlice() + for _, sb := range *sbsp { + if sb == nil { + *dbsp = append(*dbsp, nil) + } else { + *dbsp = append(*dbsp, append([]byte{}, sb...)) + } + } + if *dbsp == nil { + *dbsp = [][]byte{} + } + } + } + default: // E.g., []byte + mfi.merge = func(dst, src pointer) { + sbp := src.toBytes() + if *sbp != nil { + dbp := dst.toBytes() + if !isProto3 || len(*sbp) > 0 { + *dbp = append([]byte{}, *sbp...) + } + } + } + } + case reflect.Struct: + switch { + case !isPointer: + panic(fmt.Sprintf("message field %s without pointer", tf)) + case isSlice: // E.g., []*pb.T + mi := getMergeInfo(tf) + mfi.merge = func(dst, src pointer) { + sps := src.getPointerSlice() + if sps != nil { + dps := dst.getPointerSlice() + for _, sp := range sps { + var dp pointer + if !sp.isNil() { + dp = valToPointer(reflect.New(tf)) + mi.merge(dp, sp) + } + dps = append(dps, dp) + } + if dps == nil { + dps = []pointer{} + } + dst.setPointerSlice(dps) + } + } + default: // E.g., *pb.T + mi := getMergeInfo(tf) + mfi.merge = func(dst, src pointer) { + sp := src.getPointer() + if !sp.isNil() { + dp := dst.getPointer() + if dp.isNil() { + dp = valToPointer(reflect.New(tf)) + dst.setPointer(dp) + } + mi.merge(dp, sp) + } + } + } + case reflect.Map: + switch { + case isPointer || isSlice: + panic("bad pointer or slice in map case in " + tf.Name()) + default: // E.g., map[K]V + mfi.merge = func(dst, src pointer) { + sm := src.asPointerTo(tf).Elem() + if sm.Len() == 0 { + return + } + dm := dst.asPointerTo(tf).Elem() + if dm.IsNil() { + dm.Set(reflect.MakeMap(tf)) + } + + switch tf.Elem().Kind() { + case reflect.Ptr: // Proto struct (e.g., *T) + for _, key := range sm.MapKeys() { + val := sm.MapIndex(key) + val = reflect.ValueOf(Clone(val.Interface().(Message))) + dm.SetMapIndex(key, val) + } + case reflect.Slice: // E.g. Bytes type (e.g., []byte) + for _, key := range sm.MapKeys() { + val := sm.MapIndex(key) + val = reflect.ValueOf(append([]byte{}, val.Bytes()...)) + dm.SetMapIndex(key, val) + } + default: // Basic type (e.g., string) + for _, key := range sm.MapKeys() { + val := sm.MapIndex(key) + dm.SetMapIndex(key, val) + } + } + } + } + case reflect.Interface: + // Must be oneof field. + switch { + case isPointer || isSlice: + panic("bad pointer or slice in interface case in " + tf.Name()) + default: // E.g., interface{} + // TODO: Make this faster? + mfi.merge = func(dst, src pointer) { + su := src.asPointerTo(tf).Elem() + if !su.IsNil() { + du := dst.asPointerTo(tf).Elem() + typ := su.Elem().Type() + if du.IsNil() || du.Elem().Type() != typ { + du.Set(reflect.New(typ.Elem())) // Initialize interface if empty + } + sv := su.Elem().Elem().Field(0) + if sv.Kind() == reflect.Ptr && sv.IsNil() { + return + } + dv := du.Elem().Elem().Field(0) + if dv.Kind() == reflect.Ptr && dv.IsNil() { + dv.Set(reflect.New(sv.Type().Elem())) // Initialize proto message if empty + } + switch sv.Type().Kind() { + case reflect.Ptr: // Proto struct (e.g., *T) + Merge(dv.Interface().(Message), sv.Interface().(Message)) + case reflect.Slice: // E.g. Bytes type (e.g., []byte) + dv.Set(reflect.ValueOf(append([]byte{}, sv.Bytes()...))) + default: // Basic type (e.g., string) + dv.Set(sv) + } + } + } + } + default: + panic(fmt.Sprintf("merger not found for type:%s", tf)) + } + mi.fields = append(mi.fields, mfi) + } + + mi.unrecognized = invalidField + if f, ok := t.FieldByName("XXX_unrecognized"); ok { + if f.Type != reflect.TypeOf([]byte{}) { + panic("expected XXX_unrecognized to be of type []byte") + } + mi.unrecognized = toField(&f) + } + + atomic.StoreInt32(&mi.initialized, 1) +} diff --git a/chaincode/abac/go/vendor/github.com/golang/protobuf/proto/table_unmarshal.go b/chaincode/abac/go/vendor/github.com/golang/protobuf/proto/table_unmarshal.go new file mode 100644 index 00000000..fd4afec8 --- /dev/null +++ b/chaincode/abac/go/vendor/github.com/golang/protobuf/proto/table_unmarshal.go @@ -0,0 +1,2051 @@ +// Go support for Protocol Buffers - Google's data interchange format +// +// Copyright 2016 The Go Authors. All rights reserved. +// https://github.com/golang/protobuf +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +package proto + +import ( + "errors" + "fmt" + "io" + "math" + "reflect" + "strconv" + "strings" + "sync" + "sync/atomic" + "unicode/utf8" +) + +// Unmarshal is the entry point from the generated .pb.go files. +// This function is not intended to be used by non-generated code. +// This function is not subject to any compatibility guarantee. +// msg contains a pointer to a protocol buffer struct. +// b is the data to be unmarshaled into the protocol buffer. +// a is a pointer to a place to store cached unmarshal information. +func (a *InternalMessageInfo) Unmarshal(msg Message, b []byte) error { + // Load the unmarshal information for this message type. + // The atomic load ensures memory consistency. + u := atomicLoadUnmarshalInfo(&a.unmarshal) + if u == nil { + // Slow path: find unmarshal info for msg, update a with it. + u = getUnmarshalInfo(reflect.TypeOf(msg).Elem()) + atomicStoreUnmarshalInfo(&a.unmarshal, u) + } + // Then do the unmarshaling. + err := u.unmarshal(toPointer(&msg), b) + return err +} + +type unmarshalInfo struct { + typ reflect.Type // type of the protobuf struct + + // 0 = only typ field is initialized + // 1 = completely initialized + initialized int32 + lock sync.Mutex // prevents double initialization + dense []unmarshalFieldInfo // fields indexed by tag # + sparse map[uint64]unmarshalFieldInfo // fields indexed by tag # + reqFields []string // names of required fields + reqMask uint64 // 1< 0 { + // Read tag and wire type. + // Special case 1 and 2 byte varints. + var x uint64 + if b[0] < 128 { + x = uint64(b[0]) + b = b[1:] + } else if len(b) >= 2 && b[1] < 128 { + x = uint64(b[0]&0x7f) + uint64(b[1])<<7 + b = b[2:] + } else { + var n int + x, n = decodeVarint(b) + if n == 0 { + return io.ErrUnexpectedEOF + } + b = b[n:] + } + tag := x >> 3 + wire := int(x) & 7 + + // Dispatch on the tag to one of the unmarshal* functions below. + var f unmarshalFieldInfo + if tag < uint64(len(u.dense)) { + f = u.dense[tag] + } else { + f = u.sparse[tag] + } + if fn := f.unmarshal; fn != nil { + var err error + b, err = fn(b, m.offset(f.field), wire) + if err == nil { + reqMask |= f.reqMask + continue + } + if r, ok := err.(*RequiredNotSetError); ok { + // Remember this error, but keep parsing. We need to produce + // a full parse even if a required field is missing. + if errLater == nil { + errLater = r + } + reqMask |= f.reqMask + continue + } + if err != errInternalBadWireType { + if err == errInvalidUTF8 { + if errLater == nil { + fullName := revProtoTypes[reflect.PtrTo(u.typ)] + "." + f.name + errLater = &invalidUTF8Error{fullName} + } + continue + } + return err + } + // Fragments with bad wire type are treated as unknown fields. + } + + // Unknown tag. + if !u.unrecognized.IsValid() { + // Don't keep unrecognized data; just skip it. + var err error + b, err = skipField(b, wire) + if err != nil { + return err + } + continue + } + // Keep unrecognized data around. + // maybe in extensions, maybe in the unrecognized field. + z := m.offset(u.unrecognized).toBytes() + var emap map[int32]Extension + var e Extension + for _, r := range u.extensionRanges { + if uint64(r.Start) <= tag && tag <= uint64(r.End) { + if u.extensions.IsValid() { + mp := m.offset(u.extensions).toExtensions() + emap = mp.extensionsWrite() + e = emap[int32(tag)] + z = &e.enc + break + } + if u.oldExtensions.IsValid() { + p := m.offset(u.oldExtensions).toOldExtensions() + emap = *p + if emap == nil { + emap = map[int32]Extension{} + *p = emap + } + e = emap[int32(tag)] + z = &e.enc + break + } + panic("no extensions field available") + } + } + + // Use wire type to skip data. + var err error + b0 := b + b, err = skipField(b, wire) + if err != nil { + return err + } + *z = encodeVarint(*z, tag<<3|uint64(wire)) + *z = append(*z, b0[:len(b0)-len(b)]...) + + if emap != nil { + emap[int32(tag)] = e + } + } + if reqMask != u.reqMask && errLater == nil { + // A required field of this message is missing. + for _, n := range u.reqFields { + if reqMask&1 == 0 { + errLater = &RequiredNotSetError{n} + } + reqMask >>= 1 + } + } + return errLater +} + +// computeUnmarshalInfo fills in u with information for use +// in unmarshaling protocol buffers of type u.typ. +func (u *unmarshalInfo) computeUnmarshalInfo() { + u.lock.Lock() + defer u.lock.Unlock() + if u.initialized != 0 { + return + } + t := u.typ + n := t.NumField() + + // Set up the "not found" value for the unrecognized byte buffer. + // This is the default for proto3. + u.unrecognized = invalidField + u.extensions = invalidField + u.oldExtensions = invalidField + + // List of the generated type and offset for each oneof field. + type oneofField struct { + ityp reflect.Type // interface type of oneof field + field field // offset in containing message + } + var oneofFields []oneofField + + for i := 0; i < n; i++ { + f := t.Field(i) + if f.Name == "XXX_unrecognized" { + // The byte slice used to hold unrecognized input is special. + if f.Type != reflect.TypeOf(([]byte)(nil)) { + panic("bad type for XXX_unrecognized field: " + f.Type.Name()) + } + u.unrecognized = toField(&f) + continue + } + if f.Name == "XXX_InternalExtensions" { + // Ditto here. + if f.Type != reflect.TypeOf(XXX_InternalExtensions{}) { + panic("bad type for XXX_InternalExtensions field: " + f.Type.Name()) + } + u.extensions = toField(&f) + if f.Tag.Get("protobuf_messageset") == "1" { + u.isMessageSet = true + } + continue + } + if f.Name == "XXX_extensions" { + // An older form of the extensions field. + if f.Type != reflect.TypeOf((map[int32]Extension)(nil)) { + panic("bad type for XXX_extensions field: " + f.Type.Name()) + } + u.oldExtensions = toField(&f) + continue + } + if f.Name == "XXX_NoUnkeyedLiteral" || f.Name == "XXX_sizecache" { + continue + } + + oneof := f.Tag.Get("protobuf_oneof") + if oneof != "" { + oneofFields = append(oneofFields, oneofField{f.Type, toField(&f)}) + // The rest of oneof processing happens below. + continue + } + + tags := f.Tag.Get("protobuf") + tagArray := strings.Split(tags, ",") + if len(tagArray) < 2 { + panic("protobuf tag not enough fields in " + t.Name() + "." + f.Name + ": " + tags) + } + tag, err := strconv.Atoi(tagArray[1]) + if err != nil { + panic("protobuf tag field not an integer: " + tagArray[1]) + } + + name := "" + for _, tag := range tagArray[3:] { + if strings.HasPrefix(tag, "name=") { + name = tag[5:] + } + } + + // Extract unmarshaling function from the field (its type and tags). + unmarshal := fieldUnmarshaler(&f) + + // Required field? + var reqMask uint64 + if tagArray[2] == "req" { + bit := len(u.reqFields) + u.reqFields = append(u.reqFields, name) + reqMask = uint64(1) << uint(bit) + // TODO: if we have more than 64 required fields, we end up + // not verifying that all required fields are present. + // Fix this, perhaps using a count of required fields? + } + + // Store the info in the correct slot in the message. + u.setTag(tag, toField(&f), unmarshal, reqMask, name) + } + + // Find any types associated with oneof fields. + // TODO: XXX_OneofFuncs returns more info than we need. Get rid of some of it? + fn := reflect.Zero(reflect.PtrTo(t)).MethodByName("XXX_OneofFuncs") + if fn.IsValid() { + res := fn.Call(nil)[3] // last return value from XXX_OneofFuncs: []interface{} + for i := res.Len() - 1; i >= 0; i-- { + v := res.Index(i) // interface{} + tptr := reflect.ValueOf(v.Interface()).Type() // *Msg_X + typ := tptr.Elem() // Msg_X + + f := typ.Field(0) // oneof implementers have one field + baseUnmarshal := fieldUnmarshaler(&f) + tags := strings.Split(f.Tag.Get("protobuf"), ",") + fieldNum, err := strconv.Atoi(tags[1]) + if err != nil { + panic("protobuf tag field not an integer: " + tags[1]) + } + var name string + for _, tag := range tags { + if strings.HasPrefix(tag, "name=") { + name = strings.TrimPrefix(tag, "name=") + break + } + } + + // Find the oneof field that this struct implements. + // Might take O(n^2) to process all of the oneofs, but who cares. + for _, of := range oneofFields { + if tptr.Implements(of.ityp) { + // We have found the corresponding interface for this struct. + // That lets us know where this struct should be stored + // when we encounter it during unmarshaling. + unmarshal := makeUnmarshalOneof(typ, of.ityp, baseUnmarshal) + u.setTag(fieldNum, of.field, unmarshal, 0, name) + } + } + } + } + + // Get extension ranges, if any. + fn = reflect.Zero(reflect.PtrTo(t)).MethodByName("ExtensionRangeArray") + if fn.IsValid() { + if !u.extensions.IsValid() && !u.oldExtensions.IsValid() { + panic("a message with extensions, but no extensions field in " + t.Name()) + } + u.extensionRanges = fn.Call(nil)[0].Interface().([]ExtensionRange) + } + + // Explicitly disallow tag 0. This will ensure we flag an error + // when decoding a buffer of all zeros. Without this code, we + // would decode and skip an all-zero buffer of even length. + // [0 0] is [tag=0/wiretype=varint varint-encoded-0]. + u.setTag(0, zeroField, func(b []byte, f pointer, w int) ([]byte, error) { + return nil, fmt.Errorf("proto: %s: illegal tag 0 (wire type %d)", t, w) + }, 0, "") + + // Set mask for required field check. + u.reqMask = uint64(1)<= 0 && (tag < 16 || tag < 2*n) { // TODO: what are the right numbers here? + for len(u.dense) <= tag { + u.dense = append(u.dense, unmarshalFieldInfo{}) + } + u.dense[tag] = i + return + } + if u.sparse == nil { + u.sparse = map[uint64]unmarshalFieldInfo{} + } + u.sparse[uint64(tag)] = i +} + +// fieldUnmarshaler returns an unmarshaler for the given field. +func fieldUnmarshaler(f *reflect.StructField) unmarshaler { + if f.Type.Kind() == reflect.Map { + return makeUnmarshalMap(f) + } + return typeUnmarshaler(f.Type, f.Tag.Get("protobuf")) +} + +// typeUnmarshaler returns an unmarshaler for the given field type / field tag pair. +func typeUnmarshaler(t reflect.Type, tags string) unmarshaler { + tagArray := strings.Split(tags, ",") + encoding := tagArray[0] + name := "unknown" + proto3 := false + validateUTF8 := true + for _, tag := range tagArray[3:] { + if strings.HasPrefix(tag, "name=") { + name = tag[5:] + } + if tag == "proto3" { + proto3 = true + } + } + validateUTF8 = validateUTF8 && proto3 + + // Figure out packaging (pointer, slice, or both) + slice := false + pointer := false + if t.Kind() == reflect.Slice && t.Elem().Kind() != reflect.Uint8 { + slice = true + t = t.Elem() + } + if t.Kind() == reflect.Ptr { + pointer = true + t = t.Elem() + } + + // We'll never have both pointer and slice for basic types. + if pointer && slice && t.Kind() != reflect.Struct { + panic("both pointer and slice for basic type in " + t.Name()) + } + + switch t.Kind() { + case reflect.Bool: + if pointer { + return unmarshalBoolPtr + } + if slice { + return unmarshalBoolSlice + } + return unmarshalBoolValue + case reflect.Int32: + switch encoding { + case "fixed32": + if pointer { + return unmarshalFixedS32Ptr + } + if slice { + return unmarshalFixedS32Slice + } + return unmarshalFixedS32Value + case "varint": + // this could be int32 or enum + if pointer { + return unmarshalInt32Ptr + } + if slice { + return unmarshalInt32Slice + } + return unmarshalInt32Value + case "zigzag32": + if pointer { + return unmarshalSint32Ptr + } + if slice { + return unmarshalSint32Slice + } + return unmarshalSint32Value + } + case reflect.Int64: + switch encoding { + case "fixed64": + if pointer { + return unmarshalFixedS64Ptr + } + if slice { + return unmarshalFixedS64Slice + } + return unmarshalFixedS64Value + case "varint": + if pointer { + return unmarshalInt64Ptr + } + if slice { + return unmarshalInt64Slice + } + return unmarshalInt64Value + case "zigzag64": + if pointer { + return unmarshalSint64Ptr + } + if slice { + return unmarshalSint64Slice + } + return unmarshalSint64Value + } + case reflect.Uint32: + switch encoding { + case "fixed32": + if pointer { + return unmarshalFixed32Ptr + } + if slice { + return unmarshalFixed32Slice + } + return unmarshalFixed32Value + case "varint": + if pointer { + return unmarshalUint32Ptr + } + if slice { + return unmarshalUint32Slice + } + return unmarshalUint32Value + } + case reflect.Uint64: + switch encoding { + case "fixed64": + if pointer { + return unmarshalFixed64Ptr + } + if slice { + return unmarshalFixed64Slice + } + return unmarshalFixed64Value + case "varint": + if pointer { + return unmarshalUint64Ptr + } + if slice { + return unmarshalUint64Slice + } + return unmarshalUint64Value + } + case reflect.Float32: + if pointer { + return unmarshalFloat32Ptr + } + if slice { + return unmarshalFloat32Slice + } + return unmarshalFloat32Value + case reflect.Float64: + if pointer { + return unmarshalFloat64Ptr + } + if slice { + return unmarshalFloat64Slice + } + return unmarshalFloat64Value + case reflect.Map: + panic("map type in typeUnmarshaler in " + t.Name()) + case reflect.Slice: + if pointer { + panic("bad pointer in slice case in " + t.Name()) + } + if slice { + return unmarshalBytesSlice + } + return unmarshalBytesValue + case reflect.String: + if validateUTF8 { + if pointer { + return unmarshalUTF8StringPtr + } + if slice { + return unmarshalUTF8StringSlice + } + return unmarshalUTF8StringValue + } + if pointer { + return unmarshalStringPtr + } + if slice { + return unmarshalStringSlice + } + return unmarshalStringValue + case reflect.Struct: + // message or group field + if !pointer { + panic(fmt.Sprintf("message/group field %s:%s without pointer", t, encoding)) + } + switch encoding { + case "bytes": + if slice { + return makeUnmarshalMessageSlicePtr(getUnmarshalInfo(t), name) + } + return makeUnmarshalMessagePtr(getUnmarshalInfo(t), name) + case "group": + if slice { + return makeUnmarshalGroupSlicePtr(getUnmarshalInfo(t), name) + } + return makeUnmarshalGroupPtr(getUnmarshalInfo(t), name) + } + } + panic(fmt.Sprintf("unmarshaler not found type:%s encoding:%s", t, encoding)) +} + +// Below are all the unmarshalers for individual fields of various types. + +func unmarshalInt64Value(b []byte, f pointer, w int) ([]byte, error) { + if w != WireVarint { + return b, errInternalBadWireType + } + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + v := int64(x) + *f.toInt64() = v + return b, nil +} + +func unmarshalInt64Ptr(b []byte, f pointer, w int) ([]byte, error) { + if w != WireVarint { + return b, errInternalBadWireType + } + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + v := int64(x) + *f.toInt64Ptr() = &v + return b, nil +} + +func unmarshalInt64Slice(b []byte, f pointer, w int) ([]byte, error) { + if w == WireBytes { // packed + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + if x > uint64(len(b)) { + return nil, io.ErrUnexpectedEOF + } + res := b[x:] + b = b[:x] + for len(b) > 0 { + x, n = decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + v := int64(x) + s := f.toInt64Slice() + *s = append(*s, v) + } + return res, nil + } + if w != WireVarint { + return b, errInternalBadWireType + } + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + v := int64(x) + s := f.toInt64Slice() + *s = append(*s, v) + return b, nil +} + +func unmarshalSint64Value(b []byte, f pointer, w int) ([]byte, error) { + if w != WireVarint { + return b, errInternalBadWireType + } + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + v := int64(x>>1) ^ int64(x)<<63>>63 + *f.toInt64() = v + return b, nil +} + +func unmarshalSint64Ptr(b []byte, f pointer, w int) ([]byte, error) { + if w != WireVarint { + return b, errInternalBadWireType + } + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + v := int64(x>>1) ^ int64(x)<<63>>63 + *f.toInt64Ptr() = &v + return b, nil +} + +func unmarshalSint64Slice(b []byte, f pointer, w int) ([]byte, error) { + if w == WireBytes { // packed + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + if x > uint64(len(b)) { + return nil, io.ErrUnexpectedEOF + } + res := b[x:] + b = b[:x] + for len(b) > 0 { + x, n = decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + v := int64(x>>1) ^ int64(x)<<63>>63 + s := f.toInt64Slice() + *s = append(*s, v) + } + return res, nil + } + if w != WireVarint { + return b, errInternalBadWireType + } + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + v := int64(x>>1) ^ int64(x)<<63>>63 + s := f.toInt64Slice() + *s = append(*s, v) + return b, nil +} + +func unmarshalUint64Value(b []byte, f pointer, w int) ([]byte, error) { + if w != WireVarint { + return b, errInternalBadWireType + } + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + v := uint64(x) + *f.toUint64() = v + return b, nil +} + +func unmarshalUint64Ptr(b []byte, f pointer, w int) ([]byte, error) { + if w != WireVarint { + return b, errInternalBadWireType + } + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + v := uint64(x) + *f.toUint64Ptr() = &v + return b, nil +} + +func unmarshalUint64Slice(b []byte, f pointer, w int) ([]byte, error) { + if w == WireBytes { // packed + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + if x > uint64(len(b)) { + return nil, io.ErrUnexpectedEOF + } + res := b[x:] + b = b[:x] + for len(b) > 0 { + x, n = decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + v := uint64(x) + s := f.toUint64Slice() + *s = append(*s, v) + } + return res, nil + } + if w != WireVarint { + return b, errInternalBadWireType + } + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + v := uint64(x) + s := f.toUint64Slice() + *s = append(*s, v) + return b, nil +} + +func unmarshalInt32Value(b []byte, f pointer, w int) ([]byte, error) { + if w != WireVarint { + return b, errInternalBadWireType + } + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + v := int32(x) + *f.toInt32() = v + return b, nil +} + +func unmarshalInt32Ptr(b []byte, f pointer, w int) ([]byte, error) { + if w != WireVarint { + return b, errInternalBadWireType + } + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + v := int32(x) + f.setInt32Ptr(v) + return b, nil +} + +func unmarshalInt32Slice(b []byte, f pointer, w int) ([]byte, error) { + if w == WireBytes { // packed + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + if x > uint64(len(b)) { + return nil, io.ErrUnexpectedEOF + } + res := b[x:] + b = b[:x] + for len(b) > 0 { + x, n = decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + v := int32(x) + f.appendInt32Slice(v) + } + return res, nil + } + if w != WireVarint { + return b, errInternalBadWireType + } + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + v := int32(x) + f.appendInt32Slice(v) + return b, nil +} + +func unmarshalSint32Value(b []byte, f pointer, w int) ([]byte, error) { + if w != WireVarint { + return b, errInternalBadWireType + } + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + v := int32(x>>1) ^ int32(x)<<31>>31 + *f.toInt32() = v + return b, nil +} + +func unmarshalSint32Ptr(b []byte, f pointer, w int) ([]byte, error) { + if w != WireVarint { + return b, errInternalBadWireType + } + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + v := int32(x>>1) ^ int32(x)<<31>>31 + f.setInt32Ptr(v) + return b, nil +} + +func unmarshalSint32Slice(b []byte, f pointer, w int) ([]byte, error) { + if w == WireBytes { // packed + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + if x > uint64(len(b)) { + return nil, io.ErrUnexpectedEOF + } + res := b[x:] + b = b[:x] + for len(b) > 0 { + x, n = decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + v := int32(x>>1) ^ int32(x)<<31>>31 + f.appendInt32Slice(v) + } + return res, nil + } + if w != WireVarint { + return b, errInternalBadWireType + } + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + v := int32(x>>1) ^ int32(x)<<31>>31 + f.appendInt32Slice(v) + return b, nil +} + +func unmarshalUint32Value(b []byte, f pointer, w int) ([]byte, error) { + if w != WireVarint { + return b, errInternalBadWireType + } + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + v := uint32(x) + *f.toUint32() = v + return b, nil +} + +func unmarshalUint32Ptr(b []byte, f pointer, w int) ([]byte, error) { + if w != WireVarint { + return b, errInternalBadWireType + } + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + v := uint32(x) + *f.toUint32Ptr() = &v + return b, nil +} + +func unmarshalUint32Slice(b []byte, f pointer, w int) ([]byte, error) { + if w == WireBytes { // packed + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + if x > uint64(len(b)) { + return nil, io.ErrUnexpectedEOF + } + res := b[x:] + b = b[:x] + for len(b) > 0 { + x, n = decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + v := uint32(x) + s := f.toUint32Slice() + *s = append(*s, v) + } + return res, nil + } + if w != WireVarint { + return b, errInternalBadWireType + } + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + v := uint32(x) + s := f.toUint32Slice() + *s = append(*s, v) + return b, nil +} + +func unmarshalFixed64Value(b []byte, f pointer, w int) ([]byte, error) { + if w != WireFixed64 { + return b, errInternalBadWireType + } + if len(b) < 8 { + return nil, io.ErrUnexpectedEOF + } + v := uint64(b[0]) | uint64(b[1])<<8 | uint64(b[2])<<16 | uint64(b[3])<<24 | uint64(b[4])<<32 | uint64(b[5])<<40 | uint64(b[6])<<48 | uint64(b[7])<<56 + *f.toUint64() = v + return b[8:], nil +} + +func unmarshalFixed64Ptr(b []byte, f pointer, w int) ([]byte, error) { + if w != WireFixed64 { + return b, errInternalBadWireType + } + if len(b) < 8 { + return nil, io.ErrUnexpectedEOF + } + v := uint64(b[0]) | uint64(b[1])<<8 | uint64(b[2])<<16 | uint64(b[3])<<24 | uint64(b[4])<<32 | uint64(b[5])<<40 | uint64(b[6])<<48 | uint64(b[7])<<56 + *f.toUint64Ptr() = &v + return b[8:], nil +} + +func unmarshalFixed64Slice(b []byte, f pointer, w int) ([]byte, error) { + if w == WireBytes { // packed + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + if x > uint64(len(b)) { + return nil, io.ErrUnexpectedEOF + } + res := b[x:] + b = b[:x] + for len(b) > 0 { + if len(b) < 8 { + return nil, io.ErrUnexpectedEOF + } + v := uint64(b[0]) | uint64(b[1])<<8 | uint64(b[2])<<16 | uint64(b[3])<<24 | uint64(b[4])<<32 | uint64(b[5])<<40 | uint64(b[6])<<48 | uint64(b[7])<<56 + s := f.toUint64Slice() + *s = append(*s, v) + b = b[8:] + } + return res, nil + } + if w != WireFixed64 { + return b, errInternalBadWireType + } + if len(b) < 8 { + return nil, io.ErrUnexpectedEOF + } + v := uint64(b[0]) | uint64(b[1])<<8 | uint64(b[2])<<16 | uint64(b[3])<<24 | uint64(b[4])<<32 | uint64(b[5])<<40 | uint64(b[6])<<48 | uint64(b[7])<<56 + s := f.toUint64Slice() + *s = append(*s, v) + return b[8:], nil +} + +func unmarshalFixedS64Value(b []byte, f pointer, w int) ([]byte, error) { + if w != WireFixed64 { + return b, errInternalBadWireType + } + if len(b) < 8 { + return nil, io.ErrUnexpectedEOF + } + v := int64(b[0]) | int64(b[1])<<8 | int64(b[2])<<16 | int64(b[3])<<24 | int64(b[4])<<32 | int64(b[5])<<40 | int64(b[6])<<48 | int64(b[7])<<56 + *f.toInt64() = v + return b[8:], nil +} + +func unmarshalFixedS64Ptr(b []byte, f pointer, w int) ([]byte, error) { + if w != WireFixed64 { + return b, errInternalBadWireType + } + if len(b) < 8 { + return nil, io.ErrUnexpectedEOF + } + v := int64(b[0]) | int64(b[1])<<8 | int64(b[2])<<16 | int64(b[3])<<24 | int64(b[4])<<32 | int64(b[5])<<40 | int64(b[6])<<48 | int64(b[7])<<56 + *f.toInt64Ptr() = &v + return b[8:], nil +} + +func unmarshalFixedS64Slice(b []byte, f pointer, w int) ([]byte, error) { + if w == WireBytes { // packed + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + if x > uint64(len(b)) { + return nil, io.ErrUnexpectedEOF + } + res := b[x:] + b = b[:x] + for len(b) > 0 { + if len(b) < 8 { + return nil, io.ErrUnexpectedEOF + } + v := int64(b[0]) | int64(b[1])<<8 | int64(b[2])<<16 | int64(b[3])<<24 | int64(b[4])<<32 | int64(b[5])<<40 | int64(b[6])<<48 | int64(b[7])<<56 + s := f.toInt64Slice() + *s = append(*s, v) + b = b[8:] + } + return res, nil + } + if w != WireFixed64 { + return b, errInternalBadWireType + } + if len(b) < 8 { + return nil, io.ErrUnexpectedEOF + } + v := int64(b[0]) | int64(b[1])<<8 | int64(b[2])<<16 | int64(b[3])<<24 | int64(b[4])<<32 | int64(b[5])<<40 | int64(b[6])<<48 | int64(b[7])<<56 + s := f.toInt64Slice() + *s = append(*s, v) + return b[8:], nil +} + +func unmarshalFixed32Value(b []byte, f pointer, w int) ([]byte, error) { + if w != WireFixed32 { + return b, errInternalBadWireType + } + if len(b) < 4 { + return nil, io.ErrUnexpectedEOF + } + v := uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24 + *f.toUint32() = v + return b[4:], nil +} + +func unmarshalFixed32Ptr(b []byte, f pointer, w int) ([]byte, error) { + if w != WireFixed32 { + return b, errInternalBadWireType + } + if len(b) < 4 { + return nil, io.ErrUnexpectedEOF + } + v := uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24 + *f.toUint32Ptr() = &v + return b[4:], nil +} + +func unmarshalFixed32Slice(b []byte, f pointer, w int) ([]byte, error) { + if w == WireBytes { // packed + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + if x > uint64(len(b)) { + return nil, io.ErrUnexpectedEOF + } + res := b[x:] + b = b[:x] + for len(b) > 0 { + if len(b) < 4 { + return nil, io.ErrUnexpectedEOF + } + v := uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24 + s := f.toUint32Slice() + *s = append(*s, v) + b = b[4:] + } + return res, nil + } + if w != WireFixed32 { + return b, errInternalBadWireType + } + if len(b) < 4 { + return nil, io.ErrUnexpectedEOF + } + v := uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24 + s := f.toUint32Slice() + *s = append(*s, v) + return b[4:], nil +} + +func unmarshalFixedS32Value(b []byte, f pointer, w int) ([]byte, error) { + if w != WireFixed32 { + return b, errInternalBadWireType + } + if len(b) < 4 { + return nil, io.ErrUnexpectedEOF + } + v := int32(b[0]) | int32(b[1])<<8 | int32(b[2])<<16 | int32(b[3])<<24 + *f.toInt32() = v + return b[4:], nil +} + +func unmarshalFixedS32Ptr(b []byte, f pointer, w int) ([]byte, error) { + if w != WireFixed32 { + return b, errInternalBadWireType + } + if len(b) < 4 { + return nil, io.ErrUnexpectedEOF + } + v := int32(b[0]) | int32(b[1])<<8 | int32(b[2])<<16 | int32(b[3])<<24 + f.setInt32Ptr(v) + return b[4:], nil +} + +func unmarshalFixedS32Slice(b []byte, f pointer, w int) ([]byte, error) { + if w == WireBytes { // packed + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + if x > uint64(len(b)) { + return nil, io.ErrUnexpectedEOF + } + res := b[x:] + b = b[:x] + for len(b) > 0 { + if len(b) < 4 { + return nil, io.ErrUnexpectedEOF + } + v := int32(b[0]) | int32(b[1])<<8 | int32(b[2])<<16 | int32(b[3])<<24 + f.appendInt32Slice(v) + b = b[4:] + } + return res, nil + } + if w != WireFixed32 { + return b, errInternalBadWireType + } + if len(b) < 4 { + return nil, io.ErrUnexpectedEOF + } + v := int32(b[0]) | int32(b[1])<<8 | int32(b[2])<<16 | int32(b[3])<<24 + f.appendInt32Slice(v) + return b[4:], nil +} + +func unmarshalBoolValue(b []byte, f pointer, w int) ([]byte, error) { + if w != WireVarint { + return b, errInternalBadWireType + } + // Note: any length varint is allowed, even though any sane + // encoder will use one byte. + // See https://github.com/golang/protobuf/issues/76 + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + // TODO: check if x>1? Tests seem to indicate no. + v := x != 0 + *f.toBool() = v + return b[n:], nil +} + +func unmarshalBoolPtr(b []byte, f pointer, w int) ([]byte, error) { + if w != WireVarint { + return b, errInternalBadWireType + } + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + v := x != 0 + *f.toBoolPtr() = &v + return b[n:], nil +} + +func unmarshalBoolSlice(b []byte, f pointer, w int) ([]byte, error) { + if w == WireBytes { // packed + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + if x > uint64(len(b)) { + return nil, io.ErrUnexpectedEOF + } + res := b[x:] + b = b[:x] + for len(b) > 0 { + x, n = decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + v := x != 0 + s := f.toBoolSlice() + *s = append(*s, v) + b = b[n:] + } + return res, nil + } + if w != WireVarint { + return b, errInternalBadWireType + } + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + v := x != 0 + s := f.toBoolSlice() + *s = append(*s, v) + return b[n:], nil +} + +func unmarshalFloat64Value(b []byte, f pointer, w int) ([]byte, error) { + if w != WireFixed64 { + return b, errInternalBadWireType + } + if len(b) < 8 { + return nil, io.ErrUnexpectedEOF + } + v := math.Float64frombits(uint64(b[0]) | uint64(b[1])<<8 | uint64(b[2])<<16 | uint64(b[3])<<24 | uint64(b[4])<<32 | uint64(b[5])<<40 | uint64(b[6])<<48 | uint64(b[7])<<56) + *f.toFloat64() = v + return b[8:], nil +} + +func unmarshalFloat64Ptr(b []byte, f pointer, w int) ([]byte, error) { + if w != WireFixed64 { + return b, errInternalBadWireType + } + if len(b) < 8 { + return nil, io.ErrUnexpectedEOF + } + v := math.Float64frombits(uint64(b[0]) | uint64(b[1])<<8 | uint64(b[2])<<16 | uint64(b[3])<<24 | uint64(b[4])<<32 | uint64(b[5])<<40 | uint64(b[6])<<48 | uint64(b[7])<<56) + *f.toFloat64Ptr() = &v + return b[8:], nil +} + +func unmarshalFloat64Slice(b []byte, f pointer, w int) ([]byte, error) { + if w == WireBytes { // packed + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + if x > uint64(len(b)) { + return nil, io.ErrUnexpectedEOF + } + res := b[x:] + b = b[:x] + for len(b) > 0 { + if len(b) < 8 { + return nil, io.ErrUnexpectedEOF + } + v := math.Float64frombits(uint64(b[0]) | uint64(b[1])<<8 | uint64(b[2])<<16 | uint64(b[3])<<24 | uint64(b[4])<<32 | uint64(b[5])<<40 | uint64(b[6])<<48 | uint64(b[7])<<56) + s := f.toFloat64Slice() + *s = append(*s, v) + b = b[8:] + } + return res, nil + } + if w != WireFixed64 { + return b, errInternalBadWireType + } + if len(b) < 8 { + return nil, io.ErrUnexpectedEOF + } + v := math.Float64frombits(uint64(b[0]) | uint64(b[1])<<8 | uint64(b[2])<<16 | uint64(b[3])<<24 | uint64(b[4])<<32 | uint64(b[5])<<40 | uint64(b[6])<<48 | uint64(b[7])<<56) + s := f.toFloat64Slice() + *s = append(*s, v) + return b[8:], nil +} + +func unmarshalFloat32Value(b []byte, f pointer, w int) ([]byte, error) { + if w != WireFixed32 { + return b, errInternalBadWireType + } + if len(b) < 4 { + return nil, io.ErrUnexpectedEOF + } + v := math.Float32frombits(uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24) + *f.toFloat32() = v + return b[4:], nil +} + +func unmarshalFloat32Ptr(b []byte, f pointer, w int) ([]byte, error) { + if w != WireFixed32 { + return b, errInternalBadWireType + } + if len(b) < 4 { + return nil, io.ErrUnexpectedEOF + } + v := math.Float32frombits(uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24) + *f.toFloat32Ptr() = &v + return b[4:], nil +} + +func unmarshalFloat32Slice(b []byte, f pointer, w int) ([]byte, error) { + if w == WireBytes { // packed + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + if x > uint64(len(b)) { + return nil, io.ErrUnexpectedEOF + } + res := b[x:] + b = b[:x] + for len(b) > 0 { + if len(b) < 4 { + return nil, io.ErrUnexpectedEOF + } + v := math.Float32frombits(uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24) + s := f.toFloat32Slice() + *s = append(*s, v) + b = b[4:] + } + return res, nil + } + if w != WireFixed32 { + return b, errInternalBadWireType + } + if len(b) < 4 { + return nil, io.ErrUnexpectedEOF + } + v := math.Float32frombits(uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24) + s := f.toFloat32Slice() + *s = append(*s, v) + return b[4:], nil +} + +func unmarshalStringValue(b []byte, f pointer, w int) ([]byte, error) { + if w != WireBytes { + return b, errInternalBadWireType + } + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + if x > uint64(len(b)) { + return nil, io.ErrUnexpectedEOF + } + v := string(b[:x]) + *f.toString() = v + return b[x:], nil +} + +func unmarshalStringPtr(b []byte, f pointer, w int) ([]byte, error) { + if w != WireBytes { + return b, errInternalBadWireType + } + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + if x > uint64(len(b)) { + return nil, io.ErrUnexpectedEOF + } + v := string(b[:x]) + *f.toStringPtr() = &v + return b[x:], nil +} + +func unmarshalStringSlice(b []byte, f pointer, w int) ([]byte, error) { + if w != WireBytes { + return b, errInternalBadWireType + } + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + if x > uint64(len(b)) { + return nil, io.ErrUnexpectedEOF + } + v := string(b[:x]) + s := f.toStringSlice() + *s = append(*s, v) + return b[x:], nil +} + +func unmarshalUTF8StringValue(b []byte, f pointer, w int) ([]byte, error) { + if w != WireBytes { + return b, errInternalBadWireType + } + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + if x > uint64(len(b)) { + return nil, io.ErrUnexpectedEOF + } + v := string(b[:x]) + *f.toString() = v + if !utf8.ValidString(v) { + return b[x:], errInvalidUTF8 + } + return b[x:], nil +} + +func unmarshalUTF8StringPtr(b []byte, f pointer, w int) ([]byte, error) { + if w != WireBytes { + return b, errInternalBadWireType + } + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + if x > uint64(len(b)) { + return nil, io.ErrUnexpectedEOF + } + v := string(b[:x]) + *f.toStringPtr() = &v + if !utf8.ValidString(v) { + return b[x:], errInvalidUTF8 + } + return b[x:], nil +} + +func unmarshalUTF8StringSlice(b []byte, f pointer, w int) ([]byte, error) { + if w != WireBytes { + return b, errInternalBadWireType + } + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + if x > uint64(len(b)) { + return nil, io.ErrUnexpectedEOF + } + v := string(b[:x]) + s := f.toStringSlice() + *s = append(*s, v) + if !utf8.ValidString(v) { + return b[x:], errInvalidUTF8 + } + return b[x:], nil +} + +var emptyBuf [0]byte + +func unmarshalBytesValue(b []byte, f pointer, w int) ([]byte, error) { + if w != WireBytes { + return b, errInternalBadWireType + } + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + if x > uint64(len(b)) { + return nil, io.ErrUnexpectedEOF + } + // The use of append here is a trick which avoids the zeroing + // that would be required if we used a make/copy pair. + // We append to emptyBuf instead of nil because we want + // a non-nil result even when the length is 0. + v := append(emptyBuf[:], b[:x]...) + *f.toBytes() = v + return b[x:], nil +} + +func unmarshalBytesSlice(b []byte, f pointer, w int) ([]byte, error) { + if w != WireBytes { + return b, errInternalBadWireType + } + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + if x > uint64(len(b)) { + return nil, io.ErrUnexpectedEOF + } + v := append(emptyBuf[:], b[:x]...) + s := f.toBytesSlice() + *s = append(*s, v) + return b[x:], nil +} + +func makeUnmarshalMessagePtr(sub *unmarshalInfo, name string) unmarshaler { + return func(b []byte, f pointer, w int) ([]byte, error) { + if w != WireBytes { + return b, errInternalBadWireType + } + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + if x > uint64(len(b)) { + return nil, io.ErrUnexpectedEOF + } + // First read the message field to see if something is there. + // The semantics of multiple submessages are weird. Instead of + // the last one winning (as it is for all other fields), multiple + // submessages are merged. + v := f.getPointer() + if v.isNil() { + v = valToPointer(reflect.New(sub.typ)) + f.setPointer(v) + } + err := sub.unmarshal(v, b[:x]) + if err != nil { + if r, ok := err.(*RequiredNotSetError); ok { + r.field = name + "." + r.field + } else { + return nil, err + } + } + return b[x:], err + } +} + +func makeUnmarshalMessageSlicePtr(sub *unmarshalInfo, name string) unmarshaler { + return func(b []byte, f pointer, w int) ([]byte, error) { + if w != WireBytes { + return b, errInternalBadWireType + } + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + if x > uint64(len(b)) { + return nil, io.ErrUnexpectedEOF + } + v := valToPointer(reflect.New(sub.typ)) + err := sub.unmarshal(v, b[:x]) + if err != nil { + if r, ok := err.(*RequiredNotSetError); ok { + r.field = name + "." + r.field + } else { + return nil, err + } + } + f.appendPointer(v) + return b[x:], err + } +} + +func makeUnmarshalGroupPtr(sub *unmarshalInfo, name string) unmarshaler { + return func(b []byte, f pointer, w int) ([]byte, error) { + if w != WireStartGroup { + return b, errInternalBadWireType + } + x, y := findEndGroup(b) + if x < 0 { + return nil, io.ErrUnexpectedEOF + } + v := f.getPointer() + if v.isNil() { + v = valToPointer(reflect.New(sub.typ)) + f.setPointer(v) + } + err := sub.unmarshal(v, b[:x]) + if err != nil { + if r, ok := err.(*RequiredNotSetError); ok { + r.field = name + "." + r.field + } else { + return nil, err + } + } + return b[y:], err + } +} + +func makeUnmarshalGroupSlicePtr(sub *unmarshalInfo, name string) unmarshaler { + return func(b []byte, f pointer, w int) ([]byte, error) { + if w != WireStartGroup { + return b, errInternalBadWireType + } + x, y := findEndGroup(b) + if x < 0 { + return nil, io.ErrUnexpectedEOF + } + v := valToPointer(reflect.New(sub.typ)) + err := sub.unmarshal(v, b[:x]) + if err != nil { + if r, ok := err.(*RequiredNotSetError); ok { + r.field = name + "." + r.field + } else { + return nil, err + } + } + f.appendPointer(v) + return b[y:], err + } +} + +func makeUnmarshalMap(f *reflect.StructField) unmarshaler { + t := f.Type + kt := t.Key() + vt := t.Elem() + unmarshalKey := typeUnmarshaler(kt, f.Tag.Get("protobuf_key")) + unmarshalVal := typeUnmarshaler(vt, f.Tag.Get("protobuf_val")) + return func(b []byte, f pointer, w int) ([]byte, error) { + // The map entry is a submessage. Figure out how big it is. + if w != WireBytes { + return nil, fmt.Errorf("proto: bad wiretype for map field: got %d want %d", w, WireBytes) + } + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + if x > uint64(len(b)) { + return nil, io.ErrUnexpectedEOF + } + r := b[x:] // unused data to return + b = b[:x] // data for map entry + + // Note: we could use #keys * #values ~= 200 functions + // to do map decoding without reflection. Probably not worth it. + // Maps will be somewhat slow. Oh well. + + // Read key and value from data. + var nerr nonFatal + k := reflect.New(kt) + v := reflect.New(vt) + for len(b) > 0 { + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + wire := int(x) & 7 + b = b[n:] + + var err error + switch x >> 3 { + case 1: + b, err = unmarshalKey(b, valToPointer(k), wire) + case 2: + b, err = unmarshalVal(b, valToPointer(v), wire) + default: + err = errInternalBadWireType // skip unknown tag + } + + if nerr.Merge(err) { + continue + } + if err != errInternalBadWireType { + return nil, err + } + + // Skip past unknown fields. + b, err = skipField(b, wire) + if err != nil { + return nil, err + } + } + + // Get map, allocate if needed. + m := f.asPointerTo(t).Elem() // an addressable map[K]T + if m.IsNil() { + m.Set(reflect.MakeMap(t)) + } + + // Insert into map. + m.SetMapIndex(k.Elem(), v.Elem()) + + return r, nerr.E + } +} + +// makeUnmarshalOneof makes an unmarshaler for oneof fields. +// for: +// message Msg { +// oneof F { +// int64 X = 1; +// float64 Y = 2; +// } +// } +// typ is the type of the concrete entry for a oneof case (e.g. Msg_X). +// ityp is the interface type of the oneof field (e.g. isMsg_F). +// unmarshal is the unmarshaler for the base type of the oneof case (e.g. int64). +// Note that this function will be called once for each case in the oneof. +func makeUnmarshalOneof(typ, ityp reflect.Type, unmarshal unmarshaler) unmarshaler { + sf := typ.Field(0) + field0 := toField(&sf) + return func(b []byte, f pointer, w int) ([]byte, error) { + // Allocate holder for value. + v := reflect.New(typ) + + // Unmarshal data into holder. + // We unmarshal into the first field of the holder object. + var err error + var nerr nonFatal + b, err = unmarshal(b, valToPointer(v).offset(field0), w) + if !nerr.Merge(err) { + return nil, err + } + + // Write pointer to holder into target field. + f.asPointerTo(ityp).Elem().Set(v) + + return b, nerr.E + } +} + +// Error used by decode internally. +var errInternalBadWireType = errors.New("proto: internal error: bad wiretype") + +// skipField skips past a field of type wire and returns the remaining bytes. +func skipField(b []byte, wire int) ([]byte, error) { + switch wire { + case WireVarint: + _, k := decodeVarint(b) + if k == 0 { + return b, io.ErrUnexpectedEOF + } + b = b[k:] + case WireFixed32: + if len(b) < 4 { + return b, io.ErrUnexpectedEOF + } + b = b[4:] + case WireFixed64: + if len(b) < 8 { + return b, io.ErrUnexpectedEOF + } + b = b[8:] + case WireBytes: + m, k := decodeVarint(b) + if k == 0 || uint64(len(b)-k) < m { + return b, io.ErrUnexpectedEOF + } + b = b[uint64(k)+m:] + case WireStartGroup: + _, i := findEndGroup(b) + if i == -1 { + return b, io.ErrUnexpectedEOF + } + b = b[i:] + default: + return b, fmt.Errorf("proto: can't skip unknown wire type %d", wire) + } + return b, nil +} + +// findEndGroup finds the index of the next EndGroup tag. +// Groups may be nested, so the "next" EndGroup tag is the first +// unpaired EndGroup. +// findEndGroup returns the indexes of the start and end of the EndGroup tag. +// Returns (-1,-1) if it can't find one. +func findEndGroup(b []byte) (int, int) { + depth := 1 + i := 0 + for { + x, n := decodeVarint(b[i:]) + if n == 0 { + return -1, -1 + } + j := i + i += n + switch x & 7 { + case WireVarint: + _, k := decodeVarint(b[i:]) + if k == 0 { + return -1, -1 + } + i += k + case WireFixed32: + if len(b)-4 < i { + return -1, -1 + } + i += 4 + case WireFixed64: + if len(b)-8 < i { + return -1, -1 + } + i += 8 + case WireBytes: + m, k := decodeVarint(b[i:]) + if k == 0 { + return -1, -1 + } + i += k + if uint64(len(b)-i) < m { + return -1, -1 + } + i += int(m) + case WireStartGroup: + depth++ + case WireEndGroup: + depth-- + if depth == 0 { + return j, i + } + default: + return -1, -1 + } + } +} + +// encodeVarint appends a varint-encoded integer to b and returns the result. +func encodeVarint(b []byte, x uint64) []byte { + for x >= 1<<7 { + b = append(b, byte(x&0x7f|0x80)) + x >>= 7 + } + return append(b, byte(x)) +} + +// decodeVarint reads a varint-encoded integer from b. +// Returns the decoded integer and the number of bytes read. +// If there is an error, it returns 0,0. +func decodeVarint(b []byte) (uint64, int) { + var x, y uint64 + if len(b) == 0 { + goto bad + } + x = uint64(b[0]) + if x < 0x80 { + return x, 1 + } + x -= 0x80 + + if len(b) <= 1 { + goto bad + } + y = uint64(b[1]) + x += y << 7 + if y < 0x80 { + return x, 2 + } + x -= 0x80 << 7 + + if len(b) <= 2 { + goto bad + } + y = uint64(b[2]) + x += y << 14 + if y < 0x80 { + return x, 3 + } + x -= 0x80 << 14 + + if len(b) <= 3 { + goto bad + } + y = uint64(b[3]) + x += y << 21 + if y < 0x80 { + return x, 4 + } + x -= 0x80 << 21 + + if len(b) <= 4 { + goto bad + } + y = uint64(b[4]) + x += y << 28 + if y < 0x80 { + return x, 5 + } + x -= 0x80 << 28 + + if len(b) <= 5 { + goto bad + } + y = uint64(b[5]) + x += y << 35 + if y < 0x80 { + return x, 6 + } + x -= 0x80 << 35 + + if len(b) <= 6 { + goto bad + } + y = uint64(b[6]) + x += y << 42 + if y < 0x80 { + return x, 7 + } + x -= 0x80 << 42 + + if len(b) <= 7 { + goto bad + } + y = uint64(b[7]) + x += y << 49 + if y < 0x80 { + return x, 8 + } + x -= 0x80 << 49 + + if len(b) <= 8 { + goto bad + } + y = uint64(b[8]) + x += y << 56 + if y < 0x80 { + return x, 9 + } + x -= 0x80 << 56 + + if len(b) <= 9 { + goto bad + } + y = uint64(b[9]) + x += y << 63 + if y < 2 { + return x, 10 + } + +bad: + return 0, 0 +} diff --git a/chaincode/abac/go/vendor/github.com/golang/protobuf/proto/text.go b/chaincode/abac/go/vendor/github.com/golang/protobuf/proto/text.go index 965876bf..1aaee725 100644 --- a/chaincode/abac/go/vendor/github.com/golang/protobuf/proto/text.go +++ b/chaincode/abac/go/vendor/github.com/golang/protobuf/proto/text.go @@ -50,7 +50,6 @@ import ( var ( newline = []byte("\n") spaces = []byte(" ") - gtNewline = []byte(">\n") endBraceNewline = []byte("}\n") backslashN = []byte{'\\', 'n'} backslashR = []byte{'\\', 'r'} @@ -170,11 +169,6 @@ func writeName(w *textWriter, props *Properties) error { return nil } -// raw is the interface satisfied by RawMessage. -type raw interface { - Bytes() []byte -} - func requiresQuotes(u string) bool { // When type URL contains any characters except [0-9A-Za-z./\-]*, it must be quoted. for _, ch := range u { @@ -269,6 +263,10 @@ func (tm *TextMarshaler) writeStruct(w *textWriter, sv reflect.Value) error { props := sprops.Prop[i] name := st.Field(i).Name + if name == "XXX_NoUnkeyedLiteral" { + continue + } + if strings.HasPrefix(name, "XXX_") { // There are two XXX_ fields: // XXX_unrecognized []byte @@ -355,7 +353,7 @@ func (tm *TextMarshaler) writeStruct(w *textWriter, sv reflect.Value) error { return err } } - if err := tm.writeAny(w, key, props.mkeyprop); err != nil { + if err := tm.writeAny(w, key, props.MapKeyProp); err != nil { return err } if err := w.WriteByte('\n'); err != nil { @@ -372,7 +370,7 @@ func (tm *TextMarshaler) writeStruct(w *textWriter, sv reflect.Value) error { return err } } - if err := tm.writeAny(w, val, props.mvalprop); err != nil { + if err := tm.writeAny(w, val, props.MapValProp); err != nil { return err } if err := w.WriteByte('\n'); err != nil { @@ -436,12 +434,6 @@ func (tm *TextMarshaler) writeStruct(w *textWriter, sv reflect.Value) error { return err } } - if b, ok := fv.Interface().(raw); ok { - if err := writeRaw(w, b.Bytes()); err != nil { - return err - } - continue - } // Enums have a String method, so writeAny will work fine. if err := tm.writeAny(w, fv, props); err != nil { @@ -455,7 +447,7 @@ func (tm *TextMarshaler) writeStruct(w *textWriter, sv reflect.Value) error { // Extensions (the XXX_extensions field). pv := sv.Addr() - if _, ok := extendable(pv.Interface()); ok { + if _, err := extendable(pv.Interface()); err == nil { if err := tm.writeExtensions(w, pv); err != nil { return err } @@ -464,27 +456,6 @@ func (tm *TextMarshaler) writeStruct(w *textWriter, sv reflect.Value) error { return nil } -// writeRaw writes an uninterpreted raw message. -func writeRaw(w *textWriter, b []byte) error { - if err := w.WriteByte('<'); err != nil { - return err - } - if !w.compact { - if err := w.WriteByte('\n'); err != nil { - return err - } - } - w.indent() - if err := writeUnknownStruct(w, b); err != nil { - return err - } - w.unindent() - if err := w.WriteByte('>'); err != nil { - return err - } - return nil -} - // writeAny writes an arbitrary field. func (tm *TextMarshaler) writeAny(w *textWriter, v reflect.Value, props *Properties) error { v = reflect.Indirect(v) @@ -535,6 +506,19 @@ func (tm *TextMarshaler) writeAny(w *textWriter, v reflect.Value, props *Propert } } w.indent() + if v.CanAddr() { + // Calling v.Interface on a struct causes the reflect package to + // copy the entire struct. This is racy with the new Marshaler + // since we atomically update the XXX_sizecache. + // + // Thus, we retrieve a pointer to the struct if possible to avoid + // a race since v.Interface on the pointer doesn't copy the struct. + // + // If v is not addressable, then we are not worried about a race + // since it implies that the binary Marshaler cannot possibly be + // mutating this value. + v = v.Addr() + } if etm, ok := v.Interface().(encoding.TextMarshaler); ok { text, err := etm.MarshalText() if err != nil { @@ -543,8 +527,13 @@ func (tm *TextMarshaler) writeAny(w *textWriter, v reflect.Value, props *Propert if _, err = w.Write(text); err != nil { return err } - } else if err := tm.writeStruct(w, v); err != nil { - return err + } else { + if v.Kind() == reflect.Ptr { + v = v.Elem() + } + if err := tm.writeStruct(w, v); err != nil { + return err + } } w.unindent() if err := w.WriteByte(ket); err != nil { diff --git a/chaincode/abac/go/vendor/github.com/golang/protobuf/proto/text_parser.go b/chaincode/abac/go/vendor/github.com/golang/protobuf/proto/text_parser.go index 5e14513f..bb55a3af 100644 --- a/chaincode/abac/go/vendor/github.com/golang/protobuf/proto/text_parser.go +++ b/chaincode/abac/go/vendor/github.com/golang/protobuf/proto/text_parser.go @@ -206,7 +206,6 @@ func (p *textParser) advance() { var ( errBadUTF8 = errors.New("proto: bad UTF-8") - errBadHex = errors.New("proto: bad hexadecimal") ) func unquoteC(s string, quote rune) (string, error) { @@ -277,60 +276,47 @@ func unescape(s string) (ch string, tail string, err error) { return "?", s, nil // trigraph workaround case '\'', '"', '\\': return string(r), s, nil - case '0', '1', '2', '3', '4', '5', '6', '7', 'x', 'X': + case '0', '1', '2', '3', '4', '5', '6', '7': if len(s) < 2 { return "", "", fmt.Errorf(`\%c requires 2 following digits`, r) } - base := 8 - ss := s[:2] + ss := string(r) + s[:2] s = s[2:] - if r == 'x' || r == 'X' { - base = 16 - } else { - ss = string(r) + ss - } - i, err := strconv.ParseUint(ss, base, 8) + i, err := strconv.ParseUint(ss, 8, 8) if err != nil { - return "", "", err + return "", "", fmt.Errorf(`\%s contains non-octal digits`, ss) } return string([]byte{byte(i)}), s, nil - case 'u', 'U': - n := 4 - if r == 'U' { + case 'x', 'X', 'u', 'U': + var n int + switch r { + case 'x', 'X': + n = 2 + case 'u': + n = 4 + case 'U': n = 8 } if len(s) < n { - return "", "", fmt.Errorf(`\%c requires %d digits`, r, n) - } - - bs := make([]byte, n/2) - for i := 0; i < n; i += 2 { - a, ok1 := unhex(s[i]) - b, ok2 := unhex(s[i+1]) - if !ok1 || !ok2 { - return "", "", errBadHex - } - bs[i/2] = a<<4 | b + return "", "", fmt.Errorf(`\%c requires %d following digits`, r, n) } + ss := s[:n] s = s[n:] - return string(bs), s, nil + i, err := strconv.ParseUint(ss, 16, 64) + if err != nil { + return "", "", fmt.Errorf(`\%c%s contains non-hexadecimal digits`, r, ss) + } + if r == 'x' || r == 'X' { + return string([]byte{byte(i)}), s, nil + } + if i > utf8.MaxRune { + return "", "", fmt.Errorf(`\%c%s is not a valid Unicode code point`, r, ss) + } + return string(i), s, nil } return "", "", fmt.Errorf(`unknown escape \%c`, r) } -// Adapted from src/pkg/strconv/quote.go. -func unhex(b byte) (v byte, ok bool) { - switch { - case '0' <= b && b <= '9': - return b - '0', true - case 'a' <= b && b <= 'f': - return b - 'a' + 10, true - case 'A' <= b && b <= 'F': - return b - 'A' + 10, true - } - return 0, false -} - // Back off the parser by one token. Can only be done between calls to next(). // It makes the next advance() a no-op. func (p *textParser) back() { p.backed = true } @@ -644,17 +630,17 @@ func (p *textParser) readStruct(sv reflect.Value, terminator string) error { if err := p.consumeToken(":"); err != nil { return err } - if err := p.readAny(key, props.mkeyprop); err != nil { + if err := p.readAny(key, props.MapKeyProp); err != nil { return err } if err := p.consumeOptionalSeparator(); err != nil { return err } case "value": - if err := p.checkForColon(props.mvalprop, dst.Type().Elem()); err != nil { + if err := p.checkForColon(props.MapValProp, dst.Type().Elem()); err != nil { return err } - if err := p.readAny(val, props.mvalprop); err != nil { + if err := p.readAny(val, props.MapValProp); err != nil { return err } if err := p.consumeOptionalSeparator(); err != nil { @@ -728,6 +714,9 @@ func (p *textParser) consumeExtName() (string, error) { if tok.err != nil { return "", p.errorf("unrecognized type_url or extension name: %s", tok.err) } + if p.done && tok.value != "]" { + return "", p.errorf("unclosed type_url or extension name") + } } return strings.Join(parts, ""), nil } @@ -865,7 +854,7 @@ func (p *textParser) readAny(v reflect.Value, props *Properties) error { return p.readStruct(fv, terminator) case reflect.Uint32: if x, err := strconv.ParseUint(tok.value, 0, 32); err == nil { - fv.SetUint(x) + fv.SetUint(uint64(x)) return nil } case reflect.Uint64: @@ -883,13 +872,9 @@ func (p *textParser) readAny(v reflect.Value, props *Properties) error { // UnmarshalText returns *RequiredNotSetError. func UnmarshalText(s string, pb Message) error { if um, ok := pb.(encoding.TextUnmarshaler); ok { - err := um.UnmarshalText([]byte(s)) - return err + return um.UnmarshalText([]byte(s)) } pb.Reset() v := reflect.ValueOf(pb) - if pe := newTextParser(s).readStruct(v.Elem(), ""); pe != nil { - return pe - } - return nil + return newTextParser(s).readStruct(v.Elem(), "") } diff --git a/chaincode/abac/go/vendor/github.com/hyperledger/fabric/common/attrmgr/attrmgr.go b/chaincode/abac/go/vendor/github.com/hyperledger/fabric/core/chaincode/shim/ext/attrmgr/attrmgr.go similarity index 81% rename from chaincode/abac/go/vendor/github.com/hyperledger/fabric/common/attrmgr/attrmgr.go rename to chaincode/abac/go/vendor/github.com/hyperledger/fabric/core/chaincode/shim/ext/attrmgr/attrmgr.go index a85fbd09..a446f5a2 100644 --- a/chaincode/abac/go/vendor/github.com/hyperledger/fabric/common/attrmgr/attrmgr.go +++ b/chaincode/abac/go/vendor/github.com/hyperledger/fabric/core/chaincode/shim/ext/attrmgr/attrmgr.go @@ -28,6 +28,8 @@ import ( "encoding/json" "fmt" + "github.com/golang/protobuf/proto" + "github.com/hyperledger/fabric/protos/msp" "github.com/pkg/errors" ) @@ -132,6 +134,54 @@ func (mgr *Mgr) GetAttributesFromCert(cert *x509.Certificate) (*Attributes, erro return attrs, nil } +func (mgr *Mgr) GetAttributesFromIdemix(creator []byte) (*Attributes, error) { + if creator == nil { + return nil, errors.New("creator is nil") + } + + sid := &msp.SerializedIdentity{} + err := proto.Unmarshal(creator, sid) + if err != nil { + return nil, errors.Wrap(err, "failed to unmarshal transaction invoker's identity") + } + idemixID := &msp.SerializedIdemixIdentity{} + err = proto.Unmarshal(sid.IdBytes, idemixID) + if err != nil { + return nil, errors.Wrap(err, "failed to unmarshal transaction invoker's idemix identity") + } + // Unmarshal into attributes object + attrs := &Attributes{ + Attrs: make(map[string]string), + } + + ou := &msp.OrganizationUnit{} + err = proto.Unmarshal(idemixID.Ou, ou) + if err != nil { + return nil, errors.Wrap(err, "failed to unmarshal transaction invoker's ou") + } + attrs.Attrs["ou"] = ou.OrganizationalUnitIdentifier + + role := &msp.MSPRole{} + err = proto.Unmarshal(idemixID.Role, role) + if err != nil { + return nil, errors.Wrap(err, "failed to unmarshal transaction invoker's role") + } + var roleStr string + switch role.Role { + case 0: + roleStr = "member" + case 1: + roleStr = "admin" + case 2: + roleStr = "client" + case 3: + roleStr = "peer" + } + attrs.Attrs["role"] = roleStr + + return attrs, nil +} + // Attributes contains attribute names and values type Attributes struct { Attrs map[string]string `json:"attrs"` diff --git a/chaincode/abac/go/vendor/github.com/hyperledger/fabric/core/chaincode/lib/cid/README.md b/chaincode/abac/go/vendor/github.com/hyperledger/fabric/core/chaincode/shim/ext/cid/README.md similarity index 100% rename from chaincode/abac/go/vendor/github.com/hyperledger/fabric/core/chaincode/lib/cid/README.md rename to chaincode/abac/go/vendor/github.com/hyperledger/fabric/core/chaincode/shim/ext/cid/README.md diff --git a/chaincode/abac/go/vendor/github.com/hyperledger/fabric/core/chaincode/lib/cid/cid.go b/chaincode/abac/go/vendor/github.com/hyperledger/fabric/core/chaincode/shim/ext/cid/cid.go similarity index 90% rename from chaincode/abac/go/vendor/github.com/hyperledger/fabric/core/chaincode/lib/cid/cid.go rename to chaincode/abac/go/vendor/github.com/hyperledger/fabric/core/chaincode/shim/ext/cid/cid.go index 512367d8..30d4d0b7 100644 --- a/chaincode/abac/go/vendor/github.com/hyperledger/fabric/core/chaincode/lib/cid/cid.go +++ b/chaincode/abac/go/vendor/github.com/hyperledger/fabric/core/chaincode/shim/ext/cid/cid.go @@ -26,7 +26,7 @@ import ( "fmt" "github.com/golang/protobuf/proto" - "github.com/hyperledger/fabric/common/attrmgr" + "github.com/hyperledger/fabric/core/chaincode/shim/ext/attrmgr" "github.com/hyperledger/fabric/protos/msp" "github.com/pkg/errors" ) @@ -99,7 +99,7 @@ func New(stub ChaincodeStubInterface) (ClientIdentity, error) { // GetID returns a unique ID associated with the invoking identity. func (c *clientIdentityImpl) GetID() (string, error) { - // The leading "x509::" distinquishes this as an X509 certificate, and + // The leading "x509::" distinguishes this as an X509 certificate, and // the subject and issuer DNs uniquely identify the X509 certificate. // The resulting ID will remain the same if the certificate is renewed. id := fmt.Sprintf("x509::%s::%s", getDN(&c.cert.Subject), getDN(&c.cert.Issuer)) @@ -151,11 +151,15 @@ func (c *clientIdentityImpl) init() error { idbytes := signingID.GetIdBytes() block, _ := pem.Decode(idbytes) if block == nil { - return errors.New("Expecting a PEM-encoded X509 certificate; PEM block not found") + err := c.getAttributesFromIdemix() + if err != nil { + return errors.WithMessage(err, "identity bytes are neither X509 PEM format nor an idemix credential") + } + return nil } cert, err := x509.ParseCertificate(block.Bytes) if err != nil { - return errors.Wrap(err, "failed to parse certificate") + return errors.WithMessage(err, "failed to parse certificate") } c.cert = cert attrs, err := attrmgr.New().GetAttributesFromCert(cert) @@ -181,7 +185,17 @@ func (c *clientIdentityImpl) getIdentity() (*msp.SerializedIdentity, error) { return sid, nil } -// Get the DN (distinquished name) associated with a pkix.Name. +func (c *clientIdentityImpl) getAttributesFromIdemix() error { + creator, err := c.stub.GetCreator() + attrs, err := attrmgr.New().GetAttributesFromIdemix(creator) + if err != nil { + return errors.WithMessage(err, "failed to get attributes from the transaction invoker's idemix credential") + } + c.attrs = attrs + return nil +} + +// Get the DN (distinguished name) associated with a pkix.Name. // NOTE: This code is almost a direct copy of the String() function in // https://go-review.googlesource.com/c/go/+/67270/1/src/crypto/x509/pkix/pkix.go#26 // which returns a DN as defined by RFC 2253. diff --git a/chaincode/abac/go/vendor/github.com/hyperledger/fabric/core/chaincode/lib/cid/interfaces.go b/chaincode/abac/go/vendor/github.com/hyperledger/fabric/core/chaincode/shim/ext/cid/interfaces.go similarity index 100% rename from chaincode/abac/go/vendor/github.com/hyperledger/fabric/core/chaincode/lib/cid/interfaces.go rename to chaincode/abac/go/vendor/github.com/hyperledger/fabric/core/chaincode/shim/ext/cid/interfaces.go diff --git a/chaincode/abac/go/vendor/github.com/hyperledger/fabric/protos/msp/identities.pb.go b/chaincode/abac/go/vendor/github.com/hyperledger/fabric/protos/msp/identities.pb.go new file mode 100644 index 00000000..ddea9c95 --- /dev/null +++ b/chaincode/abac/go/vendor/github.com/hyperledger/fabric/protos/msp/identities.pb.go @@ -0,0 +1,179 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// source: msp/identities.proto + +package msp // import "github.com/hyperledger/fabric/protos/msp" + +import proto "github.com/golang/protobuf/proto" +import fmt "fmt" +import math "math" + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package + +// This struct represents an Identity +// (with its MSP identifier) to be used +// to serialize it and deserialize it +type SerializedIdentity struct { + // The identifier of the associated membership service provider + Mspid string `protobuf:"bytes,1,opt,name=mspid,proto3" json:"mspid,omitempty"` + // the Identity, serialized according to the rules of its MPS + IdBytes []byte `protobuf:"bytes,2,opt,name=id_bytes,json=idBytes,proto3" json:"id_bytes,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *SerializedIdentity) Reset() { *m = SerializedIdentity{} } +func (m *SerializedIdentity) String() string { return proto.CompactTextString(m) } +func (*SerializedIdentity) ProtoMessage() {} +func (*SerializedIdentity) Descriptor() ([]byte, []int) { + return fileDescriptor_identities_8fa8af3e5bf2070a, []int{0} +} +func (m *SerializedIdentity) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_SerializedIdentity.Unmarshal(m, b) +} +func (m *SerializedIdentity) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_SerializedIdentity.Marshal(b, m, deterministic) +} +func (dst *SerializedIdentity) XXX_Merge(src proto.Message) { + xxx_messageInfo_SerializedIdentity.Merge(dst, src) +} +func (m *SerializedIdentity) XXX_Size() int { + return xxx_messageInfo_SerializedIdentity.Size(m) +} +func (m *SerializedIdentity) XXX_DiscardUnknown() { + xxx_messageInfo_SerializedIdentity.DiscardUnknown(m) +} + +var xxx_messageInfo_SerializedIdentity proto.InternalMessageInfo + +func (m *SerializedIdentity) GetMspid() string { + if m != nil { + return m.Mspid + } + return "" +} + +func (m *SerializedIdentity) GetIdBytes() []byte { + if m != nil { + return m.IdBytes + } + return nil +} + +// This struct represents an Idemix Identity +// to be used to serialize it and deserialize it. +// The IdemixMSP will first serialize an idemix identity to bytes using +// this proto, and then uses these bytes as id_bytes in SerializedIdentity +type SerializedIdemixIdentity struct { + // nym_x is the X-component of the pseudonym elliptic curve point. + // It is a []byte representation of an amcl.BIG + // The pseudonym can be seen as a public key of the identity, it is used to verify signatures. + NymX []byte `protobuf:"bytes,1,opt,name=nym_x,json=nymX,proto3" json:"nym_x,omitempty"` + // nym_y is the Y-component of the pseudonym elliptic curve point. + // It is a []byte representation of an amcl.BIG + // The pseudonym can be seen as a public key of the identity, it is used to verify signatures. + NymY []byte `protobuf:"bytes,2,opt,name=nym_y,json=nymY,proto3" json:"nym_y,omitempty"` + // ou contains the organizational unit of the idemix identity + Ou []byte `protobuf:"bytes,3,opt,name=ou,proto3" json:"ou,omitempty"` + // role contains the role of this identity (e.g., ADMIN or MEMBER) + Role []byte `protobuf:"bytes,4,opt,name=role,proto3" json:"role,omitempty"` + // proof contains the cryptographic evidence that this identity is valid + Proof []byte `protobuf:"bytes,5,opt,name=proof,proto3" json:"proof,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *SerializedIdemixIdentity) Reset() { *m = SerializedIdemixIdentity{} } +func (m *SerializedIdemixIdentity) String() string { return proto.CompactTextString(m) } +func (*SerializedIdemixIdentity) ProtoMessage() {} +func (*SerializedIdemixIdentity) Descriptor() ([]byte, []int) { + return fileDescriptor_identities_8fa8af3e5bf2070a, []int{1} +} +func (m *SerializedIdemixIdentity) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_SerializedIdemixIdentity.Unmarshal(m, b) +} +func (m *SerializedIdemixIdentity) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_SerializedIdemixIdentity.Marshal(b, m, deterministic) +} +func (dst *SerializedIdemixIdentity) XXX_Merge(src proto.Message) { + xxx_messageInfo_SerializedIdemixIdentity.Merge(dst, src) +} +func (m *SerializedIdemixIdentity) XXX_Size() int { + return xxx_messageInfo_SerializedIdemixIdentity.Size(m) +} +func (m *SerializedIdemixIdentity) XXX_DiscardUnknown() { + xxx_messageInfo_SerializedIdemixIdentity.DiscardUnknown(m) +} + +var xxx_messageInfo_SerializedIdemixIdentity proto.InternalMessageInfo + +func (m *SerializedIdemixIdentity) GetNymX() []byte { + if m != nil { + return m.NymX + } + return nil +} + +func (m *SerializedIdemixIdentity) GetNymY() []byte { + if m != nil { + return m.NymY + } + return nil +} + +func (m *SerializedIdemixIdentity) GetOu() []byte { + if m != nil { + return m.Ou + } + return nil +} + +func (m *SerializedIdemixIdentity) GetRole() []byte { + if m != nil { + return m.Role + } + return nil +} + +func (m *SerializedIdemixIdentity) GetProof() []byte { + if m != nil { + return m.Proof + } + return nil +} + +func init() { + proto.RegisterType((*SerializedIdentity)(nil), "msp.SerializedIdentity") + proto.RegisterType((*SerializedIdemixIdentity)(nil), "msp.SerializedIdemixIdentity") +} + +func init() { proto.RegisterFile("msp/identities.proto", fileDescriptor_identities_8fa8af3e5bf2070a) } + +var fileDescriptor_identities_8fa8af3e5bf2070a = []byte{ + // 238 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x54, 0x8f, 0x3f, 0x4f, 0xc3, 0x30, + 0x10, 0x47, 0x95, 0x34, 0xe1, 0x8f, 0x55, 0x31, 0x98, 0x0e, 0x66, 0x2b, 0x9d, 0x32, 0xc5, 0x03, + 0xdf, 0xa0, 0x12, 0x03, 0x03, 0x4b, 0x58, 0x80, 0xa5, 0x6a, 0xea, 0x6b, 0x7a, 0x52, 0x2e, 0x67, + 0xd9, 0x8e, 0x54, 0x33, 0xf0, 0xd9, 0x51, 0x62, 0x40, 0xb0, 0xdd, 0xef, 0xe9, 0xe9, 0xc9, 0x16, + 0x2b, 0xf2, 0x56, 0xa3, 0x81, 0x21, 0x60, 0x40, 0xf0, 0xb5, 0x75, 0x1c, 0x58, 0x2e, 0xc8, 0xdb, + 0xcd, 0xa3, 0x90, 0x2f, 0xe0, 0x70, 0xdf, 0xe3, 0x07, 0x98, 0xa7, 0xa4, 0x44, 0xb9, 0x12, 0x25, + 0x79, 0x8b, 0x46, 0x65, 0xeb, 0xac, 0xba, 0x6e, 0xd2, 0x90, 0x77, 0xe2, 0x0a, 0xcd, 0xae, 0x8d, + 0x01, 0xbc, 0xca, 0xd7, 0x59, 0xb5, 0x6c, 0x2e, 0xd1, 0x6c, 0xa7, 0xb9, 0xf9, 0x14, 0xea, 0x5f, + 0x86, 0xf0, 0xfc, 0x1b, 0xbb, 0x15, 0xe5, 0x10, 0x69, 0x77, 0x9e, 0x63, 0xcb, 0xa6, 0x18, 0x22, + 0xbd, 0xfe, 0xc0, 0xf8, 0x1d, 0x9a, 0xe0, 0x9b, 0xbc, 0x11, 0x39, 0x8f, 0x6a, 0x31, 0x93, 0x9c, + 0x47, 0x29, 0x45, 0xe1, 0xb8, 0x07, 0x55, 0x24, 0x67, 0xba, 0xa7, 0xa7, 0x59, 0xc7, 0x7c, 0x54, + 0xe5, 0x0c, 0xd3, 0xd8, 0x3e, 0x8b, 0x7b, 0x76, 0x5d, 0x7d, 0x8a, 0x16, 0x5c, 0x0f, 0xa6, 0x03, + 0x57, 0x1f, 0xf7, 0xad, 0xc3, 0x43, 0xfa, 0xab, 0xaf, 0xc9, 0xdb, 0xf7, 0xaa, 0xc3, 0x70, 0x1a, + 0xdb, 0xfa, 0xc0, 0xa4, 0xff, 0x98, 0x3a, 0x99, 0x3a, 0x99, 0x9a, 0xbc, 0x6d, 0x2f, 0xe6, 0xfb, + 0xe1, 0x2b, 0x00, 0x00, 0xff, 0xff, 0x13, 0xdc, 0xc8, 0x62, 0x39, 0x01, 0x00, 0x00, +} diff --git a/chaincode/abac/go/vendor/github.com/hyperledger/fabric/protos/msp/identities.proto b/chaincode/abac/go/vendor/github.com/hyperledger/fabric/protos/msp/identities.proto new file mode 100644 index 00000000..fef457c8 --- /dev/null +++ b/chaincode/abac/go/vendor/github.com/hyperledger/fabric/protos/msp/identities.proto @@ -0,0 +1,49 @@ +/* +Copyright IBM Corp. All Rights Reserved. + +SPDX-License-Identifier: Apache-2.0 +*/ + + +syntax = "proto3"; + +option go_package = "github.com/hyperledger/fabric/protos/msp"; +option java_package = "org.hyperledger.fabric.protos.msp"; + +package msp; + +// This struct represents an Identity +// (with its MSP identifier) to be used +// to serialize it and deserialize it +message SerializedIdentity { + // The identifier of the associated membership service provider + string mspid = 1; + + // the Identity, serialized according to the rules of its MPS + bytes id_bytes = 2; +} + +// This struct represents an Idemix Identity +// to be used to serialize it and deserialize it. +// The IdemixMSP will first serialize an idemix identity to bytes using +// this proto, and then uses these bytes as id_bytes in SerializedIdentity +message SerializedIdemixIdentity { + // nym_x is the X-component of the pseudonym elliptic curve point. + // It is a []byte representation of an amcl.BIG + // The pseudonym can be seen as a public key of the identity, it is used to verify signatures. + bytes nym_x = 1; + + // nym_y is the Y-component of the pseudonym elliptic curve point. + // It is a []byte representation of an amcl.BIG + // The pseudonym can be seen as a public key of the identity, it is used to verify signatures. + bytes nym_y = 2; + + // ou contains the organizational unit of the idemix identity + bytes ou = 3; + + // role contains the role of this identity (e.g., ADMIN or MEMBER) + bytes role = 4; + + // proof contains the cryptographic evidence that this identity is valid + bytes proof = 5; +} \ No newline at end of file diff --git a/chaincode/abac/go/vendor/github.com/hyperledger/fabric/protos/msp/msp_config.go b/chaincode/abac/go/vendor/github.com/hyperledger/fabric/protos/msp/msp_config.go new file mode 100644 index 00000000..9394550c --- /dev/null +++ b/chaincode/abac/go/vendor/github.com/hyperledger/fabric/protos/msp/msp_config.go @@ -0,0 +1,41 @@ +/* +Copyright IBM Corp. 2017 All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package msp + +import ( + "fmt" + + "github.com/golang/protobuf/proto" +) + +func (mc *MSPConfig) VariablyOpaqueFields() []string { + return []string{"config"} +} + +func (mc *MSPConfig) VariablyOpaqueFieldProto(name string) (proto.Message, error) { + if name != mc.VariablyOpaqueFields()[0] { + return nil, fmt.Errorf("not a marshaled field: %s", name) + } + switch mc.Type { + case 0: + return &FabricMSPConfig{}, nil + case 1: + return &IdemixMSPConfig{}, nil + default: + return nil, fmt.Errorf("unable to decode MSP type: %v", mc.Type) + } +} diff --git a/chaincode/abac/go/vendor/github.com/hyperledger/fabric/protos/msp/msp_config.pb.go b/chaincode/abac/go/vendor/github.com/hyperledger/fabric/protos/msp/msp_config.pb.go new file mode 100644 index 00000000..eb9066a6 --- /dev/null +++ b/chaincode/abac/go/vendor/github.com/hyperledger/fabric/protos/msp/msp_config.pb.go @@ -0,0 +1,743 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// source: msp/msp_config.proto + +package msp // import "github.com/hyperledger/fabric/protos/msp" + +import proto "github.com/golang/protobuf/proto" +import fmt "fmt" +import math "math" + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package + +// MSPConfig collects all the configuration information for +// an MSP. The Config field should be unmarshalled in a way +// that depends on the Type +type MSPConfig struct { + // Type holds the type of the MSP; the default one would + // be of type FABRIC implementing an X.509 based provider + Type int32 `protobuf:"varint,1,opt,name=type,proto3" json:"type,omitempty"` + // Config is MSP dependent configuration info + Config []byte `protobuf:"bytes,2,opt,name=config,proto3" json:"config,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *MSPConfig) Reset() { *m = MSPConfig{} } +func (m *MSPConfig) String() string { return proto.CompactTextString(m) } +func (*MSPConfig) ProtoMessage() {} +func (*MSPConfig) Descriptor() ([]byte, []int) { + return fileDescriptor_msp_config_e749e5bd1d6d997b, []int{0} +} +func (m *MSPConfig) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_MSPConfig.Unmarshal(m, b) +} +func (m *MSPConfig) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_MSPConfig.Marshal(b, m, deterministic) +} +func (dst *MSPConfig) XXX_Merge(src proto.Message) { + xxx_messageInfo_MSPConfig.Merge(dst, src) +} +func (m *MSPConfig) XXX_Size() int { + return xxx_messageInfo_MSPConfig.Size(m) +} +func (m *MSPConfig) XXX_DiscardUnknown() { + xxx_messageInfo_MSPConfig.DiscardUnknown(m) +} + +var xxx_messageInfo_MSPConfig proto.InternalMessageInfo + +func (m *MSPConfig) GetType() int32 { + if m != nil { + return m.Type + } + return 0 +} + +func (m *MSPConfig) GetConfig() []byte { + if m != nil { + return m.Config + } + return nil +} + +// FabricMSPConfig collects all the configuration information for +// a Fabric MSP. +// Here we assume a default certificate validation policy, where +// any certificate signed by any of the listed rootCA certs would +// be considered as valid under this MSP. +// This MSP may or may not come with a signing identity. If it does, +// it can also issue signing identities. If it does not, it can only +// be used to validate and verify certificates. +type FabricMSPConfig struct { + // Name holds the identifier of the MSP; MSP identifier + // is chosen by the application that governs this MSP. + // For example, and assuming the default implementation of MSP, + // that is X.509-based and considers a single Issuer, + // this can refer to the Subject OU field or the Issuer OU field. + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` + // List of root certificates trusted by this MSP + // they are used upon certificate validation (see + // comment for IntermediateCerts below) + RootCerts [][]byte `protobuf:"bytes,2,rep,name=root_certs,json=rootCerts,proto3" json:"root_certs,omitempty"` + // List of intermediate certificates trusted by this MSP; + // they are used upon certificate validation as follows: + // validation attempts to build a path from the certificate + // to be validated (which is at one end of the path) and + // one of the certs in the RootCerts field (which is at + // the other end of the path). If the path is longer than + // 2, certificates in the middle are searched within the + // IntermediateCerts pool + IntermediateCerts [][]byte `protobuf:"bytes,3,rep,name=intermediate_certs,json=intermediateCerts,proto3" json:"intermediate_certs,omitempty"` + // Identity denoting the administrator of this MSP + Admins [][]byte `protobuf:"bytes,4,rep,name=admins,proto3" json:"admins,omitempty"` + // Identity revocation list + RevocationList [][]byte `protobuf:"bytes,5,rep,name=revocation_list,json=revocationList,proto3" json:"revocation_list,omitempty"` + // SigningIdentity holds information on the signing identity + // this peer is to use, and which is to be imported by the + // MSP defined before + SigningIdentity *SigningIdentityInfo `protobuf:"bytes,6,opt,name=signing_identity,json=signingIdentity,proto3" json:"signing_identity,omitempty"` + // OrganizationalUnitIdentifiers holds one or more + // fabric organizational unit identifiers that belong to + // this MSP configuration + OrganizationalUnitIdentifiers []*FabricOUIdentifier `protobuf:"bytes,7,rep,name=organizational_unit_identifiers,json=organizationalUnitIdentifiers,proto3" json:"organizational_unit_identifiers,omitempty"` + // FabricCryptoConfig contains the configuration parameters + // for the cryptographic algorithms used by this MSP + CryptoConfig *FabricCryptoConfig `protobuf:"bytes,8,opt,name=crypto_config,json=cryptoConfig,proto3" json:"crypto_config,omitempty"` + // List of TLS root certificates trusted by this MSP. + // They are returned by GetTLSRootCerts. + TlsRootCerts [][]byte `protobuf:"bytes,9,rep,name=tls_root_certs,json=tlsRootCerts,proto3" json:"tls_root_certs,omitempty"` + // List of TLS intermediate certificates trusted by this MSP; + // They are returned by GetTLSIntermediateCerts. + TlsIntermediateCerts [][]byte `protobuf:"bytes,10,rep,name=tls_intermediate_certs,json=tlsIntermediateCerts,proto3" json:"tls_intermediate_certs,omitempty"` + // fabric_node_ous contains the configuration to distinguish clients from peers from orderers + // based on the OUs. + FabricNodeOus *FabricNodeOUs `protobuf:"bytes,11,opt,name=fabric_node_ous,json=fabricNodeOus,proto3" json:"fabric_node_ous,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *FabricMSPConfig) Reset() { *m = FabricMSPConfig{} } +func (m *FabricMSPConfig) String() string { return proto.CompactTextString(m) } +func (*FabricMSPConfig) ProtoMessage() {} +func (*FabricMSPConfig) Descriptor() ([]byte, []int) { + return fileDescriptor_msp_config_e749e5bd1d6d997b, []int{1} +} +func (m *FabricMSPConfig) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_FabricMSPConfig.Unmarshal(m, b) +} +func (m *FabricMSPConfig) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_FabricMSPConfig.Marshal(b, m, deterministic) +} +func (dst *FabricMSPConfig) XXX_Merge(src proto.Message) { + xxx_messageInfo_FabricMSPConfig.Merge(dst, src) +} +func (m *FabricMSPConfig) XXX_Size() int { + return xxx_messageInfo_FabricMSPConfig.Size(m) +} +func (m *FabricMSPConfig) XXX_DiscardUnknown() { + xxx_messageInfo_FabricMSPConfig.DiscardUnknown(m) +} + +var xxx_messageInfo_FabricMSPConfig proto.InternalMessageInfo + +func (m *FabricMSPConfig) GetName() string { + if m != nil { + return m.Name + } + return "" +} + +func (m *FabricMSPConfig) GetRootCerts() [][]byte { + if m != nil { + return m.RootCerts + } + return nil +} + +func (m *FabricMSPConfig) GetIntermediateCerts() [][]byte { + if m != nil { + return m.IntermediateCerts + } + return nil +} + +func (m *FabricMSPConfig) GetAdmins() [][]byte { + if m != nil { + return m.Admins + } + return nil +} + +func (m *FabricMSPConfig) GetRevocationList() [][]byte { + if m != nil { + return m.RevocationList + } + return nil +} + +func (m *FabricMSPConfig) GetSigningIdentity() *SigningIdentityInfo { + if m != nil { + return m.SigningIdentity + } + return nil +} + +func (m *FabricMSPConfig) GetOrganizationalUnitIdentifiers() []*FabricOUIdentifier { + if m != nil { + return m.OrganizationalUnitIdentifiers + } + return nil +} + +func (m *FabricMSPConfig) GetCryptoConfig() *FabricCryptoConfig { + if m != nil { + return m.CryptoConfig + } + return nil +} + +func (m *FabricMSPConfig) GetTlsRootCerts() [][]byte { + if m != nil { + return m.TlsRootCerts + } + return nil +} + +func (m *FabricMSPConfig) GetTlsIntermediateCerts() [][]byte { + if m != nil { + return m.TlsIntermediateCerts + } + return nil +} + +func (m *FabricMSPConfig) GetFabricNodeOus() *FabricNodeOUs { + if m != nil { + return m.FabricNodeOus + } + return nil +} + +// FabricCryptoConfig contains configuration parameters +// for the cryptographic algorithms used by the MSP +// this configuration refers to +type FabricCryptoConfig struct { + // SignatureHashFamily is a string representing the hash family to be used + // during sign and verify operations. + // Allowed values are "SHA2" and "SHA3". + SignatureHashFamily string `protobuf:"bytes,1,opt,name=signature_hash_family,json=signatureHashFamily,proto3" json:"signature_hash_family,omitempty"` + // IdentityIdentifierHashFunction is a string representing the hash function + // to be used during the computation of the identity identifier of an MSP identity. + // Allowed values are "SHA256", "SHA384" and "SHA3_256", "SHA3_384". + IdentityIdentifierHashFunction string `protobuf:"bytes,2,opt,name=identity_identifier_hash_function,json=identityIdentifierHashFunction,proto3" json:"identity_identifier_hash_function,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *FabricCryptoConfig) Reset() { *m = FabricCryptoConfig{} } +func (m *FabricCryptoConfig) String() string { return proto.CompactTextString(m) } +func (*FabricCryptoConfig) ProtoMessage() {} +func (*FabricCryptoConfig) Descriptor() ([]byte, []int) { + return fileDescriptor_msp_config_e749e5bd1d6d997b, []int{2} +} +func (m *FabricCryptoConfig) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_FabricCryptoConfig.Unmarshal(m, b) +} +func (m *FabricCryptoConfig) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_FabricCryptoConfig.Marshal(b, m, deterministic) +} +func (dst *FabricCryptoConfig) XXX_Merge(src proto.Message) { + xxx_messageInfo_FabricCryptoConfig.Merge(dst, src) +} +func (m *FabricCryptoConfig) XXX_Size() int { + return xxx_messageInfo_FabricCryptoConfig.Size(m) +} +func (m *FabricCryptoConfig) XXX_DiscardUnknown() { + xxx_messageInfo_FabricCryptoConfig.DiscardUnknown(m) +} + +var xxx_messageInfo_FabricCryptoConfig proto.InternalMessageInfo + +func (m *FabricCryptoConfig) GetSignatureHashFamily() string { + if m != nil { + return m.SignatureHashFamily + } + return "" +} + +func (m *FabricCryptoConfig) GetIdentityIdentifierHashFunction() string { + if m != nil { + return m.IdentityIdentifierHashFunction + } + return "" +} + +// IdemixMSPConfig collects all the configuration information for +// an Idemix MSP. +type IdemixMSPConfig struct { + // Name holds the identifier of the MSP + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` + // ipk represents the (serialized) issuer public key + Ipk []byte `protobuf:"bytes,2,opt,name=ipk,proto3" json:"ipk,omitempty"` + // signer may contain crypto material to configure a default signer + Signer *IdemixMSPSignerConfig `protobuf:"bytes,3,opt,name=signer,proto3" json:"signer,omitempty"` + // revocation_pk is the public key used for revocation of credentials + RevocationPk []byte `protobuf:"bytes,4,opt,name=revocation_pk,json=revocationPk,proto3" json:"revocation_pk,omitempty"` + // epoch represents the current epoch (time interval) used for revocation + Epoch int64 `protobuf:"varint,5,opt,name=epoch,proto3" json:"epoch,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *IdemixMSPConfig) Reset() { *m = IdemixMSPConfig{} } +func (m *IdemixMSPConfig) String() string { return proto.CompactTextString(m) } +func (*IdemixMSPConfig) ProtoMessage() {} +func (*IdemixMSPConfig) Descriptor() ([]byte, []int) { + return fileDescriptor_msp_config_e749e5bd1d6d997b, []int{3} +} +func (m *IdemixMSPConfig) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_IdemixMSPConfig.Unmarshal(m, b) +} +func (m *IdemixMSPConfig) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_IdemixMSPConfig.Marshal(b, m, deterministic) +} +func (dst *IdemixMSPConfig) XXX_Merge(src proto.Message) { + xxx_messageInfo_IdemixMSPConfig.Merge(dst, src) +} +func (m *IdemixMSPConfig) XXX_Size() int { + return xxx_messageInfo_IdemixMSPConfig.Size(m) +} +func (m *IdemixMSPConfig) XXX_DiscardUnknown() { + xxx_messageInfo_IdemixMSPConfig.DiscardUnknown(m) +} + +var xxx_messageInfo_IdemixMSPConfig proto.InternalMessageInfo + +func (m *IdemixMSPConfig) GetName() string { + if m != nil { + return m.Name + } + return "" +} + +func (m *IdemixMSPConfig) GetIpk() []byte { + if m != nil { + return m.Ipk + } + return nil +} + +func (m *IdemixMSPConfig) GetSigner() *IdemixMSPSignerConfig { + if m != nil { + return m.Signer + } + return nil +} + +func (m *IdemixMSPConfig) GetRevocationPk() []byte { + if m != nil { + return m.RevocationPk + } + return nil +} + +func (m *IdemixMSPConfig) GetEpoch() int64 { + if m != nil { + return m.Epoch + } + return 0 +} + +// IdemixMSPSIgnerConfig contains the crypto material to set up an idemix signing identity +type IdemixMSPSignerConfig struct { + // cred represents the serialized idemix credential of the default signer + Cred []byte `protobuf:"bytes,1,opt,name=cred,proto3" json:"cred,omitempty"` + // sk is the secret key of the default signer, corresponding to credential Cred + Sk []byte `protobuf:"bytes,2,opt,name=sk,proto3" json:"sk,omitempty"` + // organizational_unit_identifier defines the organizational unit the default signer is in + OrganizationalUnitIdentifier string `protobuf:"bytes,3,opt,name=organizational_unit_identifier,json=organizationalUnitIdentifier,proto3" json:"organizational_unit_identifier,omitempty"` + // role defines whether the default signer is admin, peer, member or client + Role int32 `protobuf:"varint,4,opt,name=role,proto3" json:"role,omitempty"` + // enrollment_id contains the enrollment id of this signer + EnrollmentId string `protobuf:"bytes,5,opt,name=enrollment_id,json=enrollmentId,proto3" json:"enrollment_id,omitempty"` + // credential_revocation_information contains a serialized CredentialRevocationInformation + CredentialRevocationInformation []byte `protobuf:"bytes,6,opt,name=credential_revocation_information,json=credentialRevocationInformation,proto3" json:"credential_revocation_information,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *IdemixMSPSignerConfig) Reset() { *m = IdemixMSPSignerConfig{} } +func (m *IdemixMSPSignerConfig) String() string { return proto.CompactTextString(m) } +func (*IdemixMSPSignerConfig) ProtoMessage() {} +func (*IdemixMSPSignerConfig) Descriptor() ([]byte, []int) { + return fileDescriptor_msp_config_e749e5bd1d6d997b, []int{4} +} +func (m *IdemixMSPSignerConfig) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_IdemixMSPSignerConfig.Unmarshal(m, b) +} +func (m *IdemixMSPSignerConfig) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_IdemixMSPSignerConfig.Marshal(b, m, deterministic) +} +func (dst *IdemixMSPSignerConfig) XXX_Merge(src proto.Message) { + xxx_messageInfo_IdemixMSPSignerConfig.Merge(dst, src) +} +func (m *IdemixMSPSignerConfig) XXX_Size() int { + return xxx_messageInfo_IdemixMSPSignerConfig.Size(m) +} +func (m *IdemixMSPSignerConfig) XXX_DiscardUnknown() { + xxx_messageInfo_IdemixMSPSignerConfig.DiscardUnknown(m) +} + +var xxx_messageInfo_IdemixMSPSignerConfig proto.InternalMessageInfo + +func (m *IdemixMSPSignerConfig) GetCred() []byte { + if m != nil { + return m.Cred + } + return nil +} + +func (m *IdemixMSPSignerConfig) GetSk() []byte { + if m != nil { + return m.Sk + } + return nil +} + +func (m *IdemixMSPSignerConfig) GetOrganizationalUnitIdentifier() string { + if m != nil { + return m.OrganizationalUnitIdentifier + } + return "" +} + +func (m *IdemixMSPSignerConfig) GetRole() int32 { + if m != nil { + return m.Role + } + return 0 +} + +func (m *IdemixMSPSignerConfig) GetEnrollmentId() string { + if m != nil { + return m.EnrollmentId + } + return "" +} + +func (m *IdemixMSPSignerConfig) GetCredentialRevocationInformation() []byte { + if m != nil { + return m.CredentialRevocationInformation + } + return nil +} + +// SigningIdentityInfo represents the configuration information +// related to the signing identity the peer is to use for generating +// endorsements +type SigningIdentityInfo struct { + // PublicSigner carries the public information of the signing + // identity. For an X.509 provider this would be represented by + // an X.509 certificate + PublicSigner []byte `protobuf:"bytes,1,opt,name=public_signer,json=publicSigner,proto3" json:"public_signer,omitempty"` + // PrivateSigner denotes a reference to the private key of the + // peer's signing identity + PrivateSigner *KeyInfo `protobuf:"bytes,2,opt,name=private_signer,json=privateSigner,proto3" json:"private_signer,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *SigningIdentityInfo) Reset() { *m = SigningIdentityInfo{} } +func (m *SigningIdentityInfo) String() string { return proto.CompactTextString(m) } +func (*SigningIdentityInfo) ProtoMessage() {} +func (*SigningIdentityInfo) Descriptor() ([]byte, []int) { + return fileDescriptor_msp_config_e749e5bd1d6d997b, []int{5} +} +func (m *SigningIdentityInfo) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_SigningIdentityInfo.Unmarshal(m, b) +} +func (m *SigningIdentityInfo) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_SigningIdentityInfo.Marshal(b, m, deterministic) +} +func (dst *SigningIdentityInfo) XXX_Merge(src proto.Message) { + xxx_messageInfo_SigningIdentityInfo.Merge(dst, src) +} +func (m *SigningIdentityInfo) XXX_Size() int { + return xxx_messageInfo_SigningIdentityInfo.Size(m) +} +func (m *SigningIdentityInfo) XXX_DiscardUnknown() { + xxx_messageInfo_SigningIdentityInfo.DiscardUnknown(m) +} + +var xxx_messageInfo_SigningIdentityInfo proto.InternalMessageInfo + +func (m *SigningIdentityInfo) GetPublicSigner() []byte { + if m != nil { + return m.PublicSigner + } + return nil +} + +func (m *SigningIdentityInfo) GetPrivateSigner() *KeyInfo { + if m != nil { + return m.PrivateSigner + } + return nil +} + +// KeyInfo represents a (secret) key that is either already stored +// in the bccsp/keystore or key material to be imported to the +// bccsp key-store. In later versions it may contain also a +// keystore identifier +type KeyInfo struct { + // Identifier of the key inside the default keystore; this for + // the case of Software BCCSP as well as the HSM BCCSP would be + // the SKI of the key + KeyIdentifier string `protobuf:"bytes,1,opt,name=key_identifier,json=keyIdentifier,proto3" json:"key_identifier,omitempty"` + // KeyMaterial (optional) for the key to be imported; this is + // properly encoded key bytes, prefixed by the type of the key + KeyMaterial []byte `protobuf:"bytes,2,opt,name=key_material,json=keyMaterial,proto3" json:"key_material,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *KeyInfo) Reset() { *m = KeyInfo{} } +func (m *KeyInfo) String() string { return proto.CompactTextString(m) } +func (*KeyInfo) ProtoMessage() {} +func (*KeyInfo) Descriptor() ([]byte, []int) { + return fileDescriptor_msp_config_e749e5bd1d6d997b, []int{6} +} +func (m *KeyInfo) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_KeyInfo.Unmarshal(m, b) +} +func (m *KeyInfo) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_KeyInfo.Marshal(b, m, deterministic) +} +func (dst *KeyInfo) XXX_Merge(src proto.Message) { + xxx_messageInfo_KeyInfo.Merge(dst, src) +} +func (m *KeyInfo) XXX_Size() int { + return xxx_messageInfo_KeyInfo.Size(m) +} +func (m *KeyInfo) XXX_DiscardUnknown() { + xxx_messageInfo_KeyInfo.DiscardUnknown(m) +} + +var xxx_messageInfo_KeyInfo proto.InternalMessageInfo + +func (m *KeyInfo) GetKeyIdentifier() string { + if m != nil { + return m.KeyIdentifier + } + return "" +} + +func (m *KeyInfo) GetKeyMaterial() []byte { + if m != nil { + return m.KeyMaterial + } + return nil +} + +// FabricOUIdentifier represents an organizational unit and +// its related chain of trust identifier. +type FabricOUIdentifier struct { + // Certificate represents the second certificate in a certification chain. + // (Notice that the first certificate in a certification chain is supposed + // to be the certificate of an identity). + // It must correspond to the certificate of root or intermediate CA + // recognized by the MSP this message belongs to. + // Starting from this certificate, a certification chain is computed + // and bound to the OrganizationUnitIdentifier specified + Certificate []byte `protobuf:"bytes,1,opt,name=certificate,proto3" json:"certificate,omitempty"` + // OrganizationUnitIdentifier defines the organizational unit under the + // MSP identified with MSPIdentifier + OrganizationalUnitIdentifier string `protobuf:"bytes,2,opt,name=organizational_unit_identifier,json=organizationalUnitIdentifier,proto3" json:"organizational_unit_identifier,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *FabricOUIdentifier) Reset() { *m = FabricOUIdentifier{} } +func (m *FabricOUIdentifier) String() string { return proto.CompactTextString(m) } +func (*FabricOUIdentifier) ProtoMessage() {} +func (*FabricOUIdentifier) Descriptor() ([]byte, []int) { + return fileDescriptor_msp_config_e749e5bd1d6d997b, []int{7} +} +func (m *FabricOUIdentifier) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_FabricOUIdentifier.Unmarshal(m, b) +} +func (m *FabricOUIdentifier) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_FabricOUIdentifier.Marshal(b, m, deterministic) +} +func (dst *FabricOUIdentifier) XXX_Merge(src proto.Message) { + xxx_messageInfo_FabricOUIdentifier.Merge(dst, src) +} +func (m *FabricOUIdentifier) XXX_Size() int { + return xxx_messageInfo_FabricOUIdentifier.Size(m) +} +func (m *FabricOUIdentifier) XXX_DiscardUnknown() { + xxx_messageInfo_FabricOUIdentifier.DiscardUnknown(m) +} + +var xxx_messageInfo_FabricOUIdentifier proto.InternalMessageInfo + +func (m *FabricOUIdentifier) GetCertificate() []byte { + if m != nil { + return m.Certificate + } + return nil +} + +func (m *FabricOUIdentifier) GetOrganizationalUnitIdentifier() string { + if m != nil { + return m.OrganizationalUnitIdentifier + } + return "" +} + +// FabricNodeOUs contains configuration to tell apart clients from peers from orderers +// based on OUs. If NodeOUs recognition is enabled then an msp identity +// that does not contain any of the specified OU will be considered invalid. +type FabricNodeOUs struct { + // If true then an msp identity that does not contain any of the specified OU will be considered invalid. + Enable bool `protobuf:"varint,1,opt,name=enable,proto3" json:"enable,omitempty"` + // OU Identifier of the clients + ClientOuIdentifier *FabricOUIdentifier `protobuf:"bytes,2,opt,name=client_ou_identifier,json=clientOuIdentifier,proto3" json:"client_ou_identifier,omitempty"` + // OU Identifier of the peers + PeerOuIdentifier *FabricOUIdentifier `protobuf:"bytes,3,opt,name=peer_ou_identifier,json=peerOuIdentifier,proto3" json:"peer_ou_identifier,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *FabricNodeOUs) Reset() { *m = FabricNodeOUs{} } +func (m *FabricNodeOUs) String() string { return proto.CompactTextString(m) } +func (*FabricNodeOUs) ProtoMessage() {} +func (*FabricNodeOUs) Descriptor() ([]byte, []int) { + return fileDescriptor_msp_config_e749e5bd1d6d997b, []int{8} +} +func (m *FabricNodeOUs) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_FabricNodeOUs.Unmarshal(m, b) +} +func (m *FabricNodeOUs) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_FabricNodeOUs.Marshal(b, m, deterministic) +} +func (dst *FabricNodeOUs) XXX_Merge(src proto.Message) { + xxx_messageInfo_FabricNodeOUs.Merge(dst, src) +} +func (m *FabricNodeOUs) XXX_Size() int { + return xxx_messageInfo_FabricNodeOUs.Size(m) +} +func (m *FabricNodeOUs) XXX_DiscardUnknown() { + xxx_messageInfo_FabricNodeOUs.DiscardUnknown(m) +} + +var xxx_messageInfo_FabricNodeOUs proto.InternalMessageInfo + +func (m *FabricNodeOUs) GetEnable() bool { + if m != nil { + return m.Enable + } + return false +} + +func (m *FabricNodeOUs) GetClientOuIdentifier() *FabricOUIdentifier { + if m != nil { + return m.ClientOuIdentifier + } + return nil +} + +func (m *FabricNodeOUs) GetPeerOuIdentifier() *FabricOUIdentifier { + if m != nil { + return m.PeerOuIdentifier + } + return nil +} + +func init() { + proto.RegisterType((*MSPConfig)(nil), "msp.MSPConfig") + proto.RegisterType((*FabricMSPConfig)(nil), "msp.FabricMSPConfig") + proto.RegisterType((*FabricCryptoConfig)(nil), "msp.FabricCryptoConfig") + proto.RegisterType((*IdemixMSPConfig)(nil), "msp.IdemixMSPConfig") + proto.RegisterType((*IdemixMSPSignerConfig)(nil), "msp.IdemixMSPSignerConfig") + proto.RegisterType((*SigningIdentityInfo)(nil), "msp.SigningIdentityInfo") + proto.RegisterType((*KeyInfo)(nil), "msp.KeyInfo") + proto.RegisterType((*FabricOUIdentifier)(nil), "msp.FabricOUIdentifier") + proto.RegisterType((*FabricNodeOUs)(nil), "msp.FabricNodeOUs") +} + +func init() { proto.RegisterFile("msp/msp_config.proto", fileDescriptor_msp_config_e749e5bd1d6d997b) } + +var fileDescriptor_msp_config_e749e5bd1d6d997b = []byte{ + // 847 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x55, 0x5f, 0x6f, 0xe3, 0x44, + 0x10, 0x57, 0x92, 0x26, 0x77, 0x99, 0x38, 0x49, 0xd9, 0xeb, 0x15, 0x0b, 0x71, 0x77, 0xa9, 0x01, + 0x91, 0x17, 0x52, 0xa9, 0x87, 0x84, 0x84, 0x78, 0xba, 0xc2, 0x09, 0x03, 0xa5, 0xd5, 0x56, 0x7d, + 0xe1, 0xc5, 0xda, 0xd8, 0x9b, 0x64, 0x65, 0x7b, 0xd7, 0xda, 0x5d, 0x9f, 0x08, 0xe2, 0x99, 0x2f, + 0xc0, 0x77, 0xe0, 0x99, 0x57, 0xbe, 0x1d, 0xda, 0x3f, 0x8d, 0x9d, 0x6b, 0x15, 0x78, 0x9b, 0x9d, + 0xf9, 0xcd, 0xcf, 0xb3, 0xbf, 0x99, 0x59, 0xc3, 0x49, 0xa9, 0xaa, 0xf3, 0x52, 0x55, 0x49, 0x2a, + 0xf8, 0x8a, 0xad, 0x17, 0x95, 0x14, 0x5a, 0xa0, 0x5e, 0xa9, 0xaa, 0xe8, 0x2b, 0x18, 0x5e, 0xdd, + 0xde, 0x5c, 0x5a, 0x3f, 0x42, 0x70, 0xa4, 0xb7, 0x15, 0x0d, 0x3b, 0xb3, 0xce, 0xbc, 0x8f, 0xad, + 0x8d, 0x4e, 0x61, 0xe0, 0xb2, 0xc2, 0xee, 0xac, 0x33, 0x0f, 0xb0, 0x3f, 0x45, 0x7f, 0x1f, 0xc1, + 0xf4, 0x2d, 0x59, 0x4a, 0x96, 0xee, 0xe5, 0x73, 0x52, 0xba, 0xfc, 0x21, 0xb6, 0x36, 0x7a, 0x01, + 0x20, 0x85, 0xd0, 0x49, 0x4a, 0xa5, 0x56, 0x61, 0x77, 0xd6, 0x9b, 0x07, 0x78, 0x68, 0x3c, 0x97, + 0xc6, 0x81, 0xbe, 0x00, 0xc4, 0xb8, 0xa6, 0xb2, 0xa4, 0x19, 0x23, 0x9a, 0x7a, 0x58, 0xcf, 0xc2, + 0x3e, 0x68, 0x47, 0x1c, 0xfc, 0x14, 0x06, 0x24, 0x2b, 0x19, 0x57, 0xe1, 0x91, 0x85, 0xf8, 0x13, + 0xfa, 0x1c, 0xa6, 0x92, 0xbe, 0x13, 0x29, 0xd1, 0x4c, 0xf0, 0xa4, 0x60, 0x4a, 0x87, 0x7d, 0x0b, + 0x98, 0x34, 0xee, 0x9f, 0x98, 0xd2, 0xe8, 0x12, 0x8e, 0x15, 0x5b, 0x73, 0xc6, 0xd7, 0x09, 0xcb, + 0x28, 0xd7, 0x4c, 0x6f, 0xc3, 0xc1, 0xac, 0x33, 0x1f, 0x5d, 0x84, 0x8b, 0x52, 0x55, 0x8b, 0x5b, + 0x17, 0x8c, 0x7d, 0x2c, 0xe6, 0x2b, 0x81, 0xa7, 0x6a, 0xdf, 0x89, 0x12, 0x78, 0x25, 0xe4, 0x9a, + 0x70, 0xf6, 0x9b, 0x25, 0x26, 0x45, 0x52, 0x73, 0xa6, 0x3d, 0xe1, 0x8a, 0x51, 0xa9, 0xc2, 0x27, + 0xb3, 0xde, 0x7c, 0x74, 0xf1, 0xa1, 0xe5, 0x74, 0x32, 0x5d, 0xdf, 0xc5, 0xbb, 0x38, 0x7e, 0xb1, + 0x9f, 0x7f, 0xc7, 0x99, 0x6e, 0xa2, 0x0a, 0x7d, 0x03, 0xe3, 0x54, 0x6e, 0x2b, 0x2d, 0x7c, 0xc7, + 0xc2, 0xa7, 0xb6, 0xc4, 0x36, 0xdd, 0xa5, 0x8d, 0x3b, 0xe1, 0x71, 0x90, 0xb6, 0x4e, 0xe8, 0x53, + 0x98, 0xe8, 0x42, 0x25, 0x2d, 0xd9, 0x87, 0x56, 0x8b, 0x40, 0x17, 0x0a, 0xef, 0x94, 0xff, 0x12, + 0x4e, 0x0d, 0xea, 0x11, 0xf5, 0xc1, 0xa2, 0x4f, 0x74, 0xa1, 0xe2, 0x07, 0x0d, 0xf8, 0x1a, 0xa6, + 0x2b, 0xfb, 0xfd, 0x84, 0x8b, 0x8c, 0x26, 0xa2, 0x56, 0xe1, 0xc8, 0xd6, 0x86, 0x5a, 0xb5, 0xfd, + 0x2c, 0x32, 0x7a, 0x7d, 0xa7, 0xf0, 0x78, 0xd5, 0x1c, 0x6b, 0x15, 0xfd, 0xd9, 0x01, 0xf4, 0xb0, + 0x78, 0x74, 0x01, 0xcf, 0x8d, 0xc0, 0x44, 0xd7, 0x92, 0x26, 0x1b, 0xa2, 0x36, 0xc9, 0x8a, 0x94, + 0xac, 0xd8, 0xfa, 0x31, 0x7a, 0xb6, 0x0b, 0x7e, 0x4f, 0xd4, 0xe6, 0xad, 0x0d, 0xa1, 0x18, 0xce, + 0xee, 0xdb, 0xd7, 0x92, 0xdd, 0x67, 0xd7, 0x3c, 0x35, 0xb2, 0xda, 0x81, 0x1d, 0xe2, 0x97, 0xf7, + 0xc0, 0x46, 0x60, 0x4b, 0xe4, 0x51, 0xd1, 0x5f, 0x1d, 0x98, 0xc6, 0x19, 0x2d, 0xd9, 0xaf, 0x87, + 0x07, 0xf9, 0x18, 0x7a, 0xac, 0xca, 0xfd, 0x16, 0x18, 0x13, 0x5d, 0xc0, 0xc0, 0xd4, 0x46, 0x65, + 0xd8, 0xb3, 0x12, 0x7c, 0x64, 0x25, 0xd8, 0x71, 0xdd, 0xda, 0x98, 0xef, 0x90, 0x47, 0xa2, 0x4f, + 0x60, 0xdc, 0x1a, 0xd4, 0x2a, 0x0f, 0x8f, 0x2c, 0x5f, 0xd0, 0x38, 0x6f, 0x72, 0x74, 0x02, 0x7d, + 0x5a, 0x89, 0x74, 0x13, 0xf6, 0x67, 0x9d, 0x79, 0x0f, 0xbb, 0x43, 0xf4, 0x47, 0x17, 0x9e, 0x3f, + 0x4a, 0x6e, 0xca, 0x4d, 0x25, 0xcd, 0x6c, 0xb9, 0x01, 0xb6, 0x36, 0x9a, 0x40, 0x57, 0xdd, 0x57, + 0xdb, 0x55, 0x39, 0xfa, 0x16, 0x5e, 0x1e, 0x9e, 0x59, 0x7b, 0x89, 0x21, 0xfe, 0xf8, 0xd0, 0x64, + 0x9a, 0x2f, 0x49, 0x51, 0x50, 0x5b, 0x75, 0x1f, 0x5b, 0xdb, 0x5c, 0x89, 0x72, 0x29, 0x8a, 0xa2, + 0xa4, 0xdc, 0x10, 0xda, 0xaa, 0x87, 0x38, 0x68, 0x9c, 0x71, 0x86, 0x7e, 0x80, 0x33, 0x53, 0x96, + 0x21, 0x22, 0x45, 0xd2, 0x92, 0x80, 0xf1, 0x95, 0x90, 0xa5, 0xb5, 0xed, 0x22, 0x06, 0xf8, 0x55, + 0x03, 0xc4, 0x3b, 0x5c, 0xdc, 0xc0, 0x22, 0x01, 0xcf, 0x1e, 0x59, 0x53, 0x53, 0x47, 0x55, 0x2f, + 0x0b, 0x96, 0x26, 0xbe, 0x2b, 0x4e, 0x8e, 0xc0, 0x39, 0x9d, 0x60, 0xe8, 0x35, 0x4c, 0x2a, 0xc9, + 0xde, 0x99, 0x61, 0xf7, 0xa8, 0xae, 0xed, 0x5d, 0x60, 0x7b, 0xf7, 0x23, 0x75, 0x1b, 0x3f, 0xf6, + 0x18, 0x97, 0x14, 0xdd, 0xc2, 0x13, 0x1f, 0x41, 0x9f, 0xc1, 0x24, 0xa7, 0xed, 0x99, 0xf3, 0x33, + 0x32, 0xce, 0x69, 0x6b, 0xc0, 0xd0, 0x19, 0x04, 0x06, 0x56, 0x12, 0x4d, 0x25, 0x23, 0x85, 0xef, + 0xc3, 0x28, 0xa7, 0xdb, 0x2b, 0xef, 0x8a, 0x7e, 0xbf, 0x5f, 0x86, 0xf6, 0xc3, 0x80, 0x66, 0x30, + 0x32, 0x4b, 0xc8, 0x56, 0x2c, 0x25, 0x9a, 0xfa, 0x2b, 0xb4, 0x5d, 0xff, 0xa3, 0x91, 0xdd, 0xff, + 0x6e, 0x64, 0xf4, 0x4f, 0x07, 0xc6, 0x7b, 0xcb, 0x6a, 0x9e, 0x56, 0xca, 0xc9, 0xb2, 0x70, 0x1f, + 0x7d, 0x8a, 0xfd, 0x09, 0xc5, 0x70, 0x92, 0x16, 0xcc, 0xb4, 0x56, 0xd4, 0xef, 0x7f, 0xe5, 0xc0, + 0x0b, 0x87, 0x5c, 0xd2, 0x75, 0xdd, 0xba, 0xdc, 0x77, 0x80, 0x2a, 0x4a, 0xe5, 0x7b, 0x44, 0xbd, + 0xc3, 0x44, 0xc7, 0x26, 0xa5, 0x4d, 0xf3, 0x26, 0x81, 0x33, 0x21, 0xd7, 0x8b, 0xcd, 0xb6, 0xa2, + 0xb2, 0xa0, 0xd9, 0x9a, 0xca, 0x85, 0x7b, 0x68, 0xdc, 0x8f, 0x4d, 0x19, 0xa6, 0x37, 0xc7, 0x57, + 0xaa, 0x72, 0xeb, 0x71, 0x43, 0xd2, 0x9c, 0xac, 0xe9, 0x2f, 0xf3, 0x35, 0xd3, 0x9b, 0x7a, 0xb9, + 0x48, 0x45, 0x79, 0xde, 0xca, 0x3d, 0x77, 0xb9, 0xe7, 0x2e, 0xd7, 0xfc, 0x26, 0x97, 0x03, 0x6b, + 0xbf, 0xfe, 0x37, 0x00, 0x00, 0xff, 0xff, 0x54, 0x67, 0x46, 0xdb, 0x38, 0x07, 0x00, 0x00, +} diff --git a/chaincode/abac/go/vendor/github.com/hyperledger/fabric/protos/msp/msp_config.proto b/chaincode/abac/go/vendor/github.com/hyperledger/fabric/protos/msp/msp_config.proto new file mode 100644 index 00000000..542f06d8 --- /dev/null +++ b/chaincode/abac/go/vendor/github.com/hyperledger/fabric/protos/msp/msp_config.proto @@ -0,0 +1,208 @@ +/* +Copyright IBM Corp. All Rights Reserved. + +SPDX-License-Identifier: Apache-2.0 +*/ + +syntax = "proto3"; + +option go_package = "github.com/hyperledger/fabric/protos/msp"; +option java_package = "org.hyperledger.fabric.protos.msp"; +option java_outer_classname = "MspConfigPackage"; + +package msp; + +// MSPConfig collects all the configuration information for +// an MSP. The Config field should be unmarshalled in a way +// that depends on the Type +message MSPConfig { + // Type holds the type of the MSP; the default one would + // be of type FABRIC implementing an X.509 based provider + int32 type = 1; + + // Config is MSP dependent configuration info + bytes config = 2; +} + +// FabricMSPConfig collects all the configuration information for +// a Fabric MSP. +// Here we assume a default certificate validation policy, where +// any certificate signed by any of the listed rootCA certs would +// be considered as valid under this MSP. +// This MSP may or may not come with a signing identity. If it does, +// it can also issue signing identities. If it does not, it can only +// be used to validate and verify certificates. +message FabricMSPConfig { + // Name holds the identifier of the MSP; MSP identifier + // is chosen by the application that governs this MSP. + // For example, and assuming the default implementation of MSP, + // that is X.509-based and considers a single Issuer, + // this can refer to the Subject OU field or the Issuer OU field. + string name = 1; + + // List of root certificates trusted by this MSP + // they are used upon certificate validation (see + // comment for IntermediateCerts below) + repeated bytes root_certs = 2; + + // List of intermediate certificates trusted by this MSP; + // they are used upon certificate validation as follows: + // validation attempts to build a path from the certificate + // to be validated (which is at one end of the path) and + // one of the certs in the RootCerts field (which is at + // the other end of the path). If the path is longer than + // 2, certificates in the middle are searched within the + // IntermediateCerts pool + repeated bytes intermediate_certs = 3; + + // Identity denoting the administrator of this MSP + repeated bytes admins = 4; + + // Identity revocation list + repeated bytes revocation_list = 5; + + // SigningIdentity holds information on the signing identity + // this peer is to use, and which is to be imported by the + // MSP defined before + SigningIdentityInfo signing_identity = 6; + + // OrganizationalUnitIdentifiers holds one or more + // fabric organizational unit identifiers that belong to + // this MSP configuration + repeated FabricOUIdentifier organizational_unit_identifiers = 7; + + // FabricCryptoConfig contains the configuration parameters + // for the cryptographic algorithms used by this MSP + FabricCryptoConfig crypto_config = 8; + + // List of TLS root certificates trusted by this MSP. + // They are returned by GetTLSRootCerts. + repeated bytes tls_root_certs = 9; + + // List of TLS intermediate certificates trusted by this MSP; + // They are returned by GetTLSIntermediateCerts. + repeated bytes tls_intermediate_certs = 10; + + // fabric_node_ous contains the configuration to distinguish clients from peers from orderers + // based on the OUs. + FabricNodeOUs fabric_node_ous = 11; +} + +// FabricCryptoConfig contains configuration parameters +// for the cryptographic algorithms used by the MSP +// this configuration refers to +message FabricCryptoConfig { + + // SignatureHashFamily is a string representing the hash family to be used + // during sign and verify operations. + // Allowed values are "SHA2" and "SHA3". + string signature_hash_family = 1; + + // IdentityIdentifierHashFunction is a string representing the hash function + // to be used during the computation of the identity identifier of an MSP identity. + // Allowed values are "SHA256", "SHA384" and "SHA3_256", "SHA3_384". + string identity_identifier_hash_function = 2; + +} + +// IdemixMSPConfig collects all the configuration information for +// an Idemix MSP. +message IdemixMSPConfig { + // Name holds the identifier of the MSP + string name = 1; + + // ipk represents the (serialized) issuer public key + bytes ipk = 2; + + // signer may contain crypto material to configure a default signer + IdemixMSPSignerConfig signer = 3; + + // revocation_pk is the public key used for revocation of credentials + bytes revocation_pk = 4; + + // epoch represents the current epoch (time interval) used for revocation + int64 epoch = 5; +} + +// IdemixMSPSIgnerConfig contains the crypto material to set up an idemix signing identity +message IdemixMSPSignerConfig { + // cred represents the serialized idemix credential of the default signer + bytes cred = 1; + + // sk is the secret key of the default signer, corresponding to credential Cred + bytes sk = 2; + + // organizational_unit_identifier defines the organizational unit the default signer is in + string organizational_unit_identifier = 3; + + // role defines whether the default signer is admin, peer, member or client + int32 role = 4; + + // enrollment_id contains the enrollment id of this signer + string enrollment_id = 5; + + // credential_revocation_information contains a serialized CredentialRevocationInformation + bytes credential_revocation_information = 6; +} + +// SigningIdentityInfo represents the configuration information +// related to the signing identity the peer is to use for generating +// endorsements +message SigningIdentityInfo { + // PublicSigner carries the public information of the signing + // identity. For an X.509 provider this would be represented by + // an X.509 certificate + bytes public_signer = 1; + + // PrivateSigner denotes a reference to the private key of the + // peer's signing identity + KeyInfo private_signer = 2; +} + +// KeyInfo represents a (secret) key that is either already stored +// in the bccsp/keystore or key material to be imported to the +// bccsp key-store. In later versions it may contain also a +// keystore identifier +message KeyInfo { + // Identifier of the key inside the default keystore; this for + // the case of Software BCCSP as well as the HSM BCCSP would be + // the SKI of the key + string key_identifier = 1; + + // KeyMaterial (optional) for the key to be imported; this is + // properly encoded key bytes, prefixed by the type of the key + bytes key_material = 2; +} + +// FabricOUIdentifier represents an organizational unit and +// its related chain of trust identifier. +message FabricOUIdentifier { + + // Certificate represents the second certificate in a certification chain. + // (Notice that the first certificate in a certification chain is supposed + // to be the certificate of an identity). + // It must correspond to the certificate of root or intermediate CA + // recognized by the MSP this message belongs to. + // Starting from this certificate, a certification chain is computed + // and bound to the OrganizationUnitIdentifier specified + bytes certificate = 1; + + // OrganizationUnitIdentifier defines the organizational unit under the + // MSP identified with MSPIdentifier + string organizational_unit_identifier = 2; +} + +// FabricNodeOUs contains configuration to tell apart clients from peers from orderers +// based on OUs. If NodeOUs recognition is enabled then an msp identity +// that does not contain any of the specified OU will be considered invalid. +message FabricNodeOUs { + // If true then an msp identity that does not contain any of the specified OU will be considered invalid. + bool enable = 1; + + // OU Identifier of the clients + FabricOUIdentifier client_ou_identifier = 2; + + // OU Identifier of the peers + FabricOUIdentifier peer_ou_identifier = 3; + +} \ No newline at end of file diff --git a/chaincode/abac/go/vendor/github.com/hyperledger/fabric/protos/msp/msp_principal.go b/chaincode/abac/go/vendor/github.com/hyperledger/fabric/protos/msp/msp_principal.go new file mode 100644 index 00000000..339dc629 --- /dev/null +++ b/chaincode/abac/go/vendor/github.com/hyperledger/fabric/protos/msp/msp_principal.go @@ -0,0 +1,43 @@ +/* +Copyright IBM Corp. 2017 All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package msp + +import ( + "fmt" + + "github.com/golang/protobuf/proto" +) + +func (mp *MSPPrincipal) VariablyOpaqueFields() []string { + return []string{"principal"} +} + +func (mp *MSPPrincipal) VariablyOpaqueFieldProto(name string) (proto.Message, error) { + if name != mp.VariablyOpaqueFields()[0] { + return nil, fmt.Errorf("not a marshaled field: %s", name) + } + switch mp.PrincipalClassification { + case MSPPrincipal_ROLE: + return &MSPRole{}, nil + case MSPPrincipal_ORGANIZATION_UNIT: + return &OrganizationUnit{}, nil + case MSPPrincipal_IDENTITY: + return nil, fmt.Errorf("unable to decode MSP type IDENTITY until the protos are fixed to include the IDENTITY proto in protos/msp") + default: + return nil, fmt.Errorf("unable to decode MSP type: %v", mp.PrincipalClassification) + } +} diff --git a/chaincode/abac/go/vendor/github.com/hyperledger/fabric/protos/msp/msp_principal.pb.go b/chaincode/abac/go/vendor/github.com/hyperledger/fabric/protos/msp/msp_principal.pb.go new file mode 100644 index 00000000..9200e97f --- /dev/null +++ b/chaincode/abac/go/vendor/github.com/hyperledger/fabric/protos/msp/msp_principal.pb.go @@ -0,0 +1,437 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// source: msp/msp_principal.proto + +package msp // import "github.com/hyperledger/fabric/protos/msp" + +import proto "github.com/golang/protobuf/proto" +import fmt "fmt" +import math "math" + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package + +type MSPPrincipal_Classification int32 + +const ( + MSPPrincipal_ROLE MSPPrincipal_Classification = 0 + // one of a member of MSP network, and the one of an + // administrator of an MSP network + MSPPrincipal_ORGANIZATION_UNIT MSPPrincipal_Classification = 1 + // groupping of entities, per MSP affiliation + // E.g., this can well be represented by an MSP's + // Organization unit + MSPPrincipal_IDENTITY MSPPrincipal_Classification = 2 + // identity + MSPPrincipal_ANONYMITY MSPPrincipal_Classification = 3 + // an identity to be anonymous or nominal. + MSPPrincipal_COMBINED MSPPrincipal_Classification = 4 +) + +var MSPPrincipal_Classification_name = map[int32]string{ + 0: "ROLE", + 1: "ORGANIZATION_UNIT", + 2: "IDENTITY", + 3: "ANONYMITY", + 4: "COMBINED", +} +var MSPPrincipal_Classification_value = map[string]int32{ + "ROLE": 0, + "ORGANIZATION_UNIT": 1, + "IDENTITY": 2, + "ANONYMITY": 3, + "COMBINED": 4, +} + +func (x MSPPrincipal_Classification) String() string { + return proto.EnumName(MSPPrincipal_Classification_name, int32(x)) +} +func (MSPPrincipal_Classification) EnumDescriptor() ([]byte, []int) { + return fileDescriptor_msp_principal_9016cf1a8a7156cd, []int{0, 0} +} + +type MSPRole_MSPRoleType int32 + +const ( + MSPRole_MEMBER MSPRole_MSPRoleType = 0 + MSPRole_ADMIN MSPRole_MSPRoleType = 1 + MSPRole_CLIENT MSPRole_MSPRoleType = 2 + MSPRole_PEER MSPRole_MSPRoleType = 3 +) + +var MSPRole_MSPRoleType_name = map[int32]string{ + 0: "MEMBER", + 1: "ADMIN", + 2: "CLIENT", + 3: "PEER", +} +var MSPRole_MSPRoleType_value = map[string]int32{ + "MEMBER": 0, + "ADMIN": 1, + "CLIENT": 2, + "PEER": 3, +} + +func (x MSPRole_MSPRoleType) String() string { + return proto.EnumName(MSPRole_MSPRoleType_name, int32(x)) +} +func (MSPRole_MSPRoleType) EnumDescriptor() ([]byte, []int) { + return fileDescriptor_msp_principal_9016cf1a8a7156cd, []int{2, 0} +} + +type MSPIdentityAnonymity_MSPIdentityAnonymityType int32 + +const ( + MSPIdentityAnonymity_NOMINAL MSPIdentityAnonymity_MSPIdentityAnonymityType = 0 + MSPIdentityAnonymity_ANONYMOUS MSPIdentityAnonymity_MSPIdentityAnonymityType = 1 +) + +var MSPIdentityAnonymity_MSPIdentityAnonymityType_name = map[int32]string{ + 0: "NOMINAL", + 1: "ANONYMOUS", +} +var MSPIdentityAnonymity_MSPIdentityAnonymityType_value = map[string]int32{ + "NOMINAL": 0, + "ANONYMOUS": 1, +} + +func (x MSPIdentityAnonymity_MSPIdentityAnonymityType) String() string { + return proto.EnumName(MSPIdentityAnonymity_MSPIdentityAnonymityType_name, int32(x)) +} +func (MSPIdentityAnonymity_MSPIdentityAnonymityType) EnumDescriptor() ([]byte, []int) { + return fileDescriptor_msp_principal_9016cf1a8a7156cd, []int{3, 0} +} + +// MSPPrincipal aims to represent an MSP-centric set of identities. +// In particular, this structure allows for definition of +// - a group of identities that are member of the same MSP +// - a group of identities that are member of the same organization unit +// in the same MSP +// - a group of identities that are administering a specific MSP +// - a specific identity +// Expressing these groups is done given two fields of the fields below +// - Classification, that defines the type of classification of identities +// in an MSP this principal would be defined on; Classification can take +// three values: +// (i) ByMSPRole: that represents a classification of identities within +// MSP based on one of the two pre-defined MSP rules, "member" and "admin" +// (ii) ByOrganizationUnit: that represents a classification of identities +// within MSP based on the organization unit an identity belongs to +// (iii)ByIdentity that denotes that MSPPrincipal is mapped to a single +// identity/certificate; this would mean that the Principal bytes +// message +type MSPPrincipal struct { + // Classification describes the way that one should process + // Principal. An Classification value of "ByOrganizationUnit" reflects + // that "Principal" contains the name of an organization this MSP + // handles. A Classification value "ByIdentity" means that + // "Principal" contains a specific identity. Default value + // denotes that Principal contains one of the groups by + // default supported by all MSPs ("admin" or "member"). + PrincipalClassification MSPPrincipal_Classification `protobuf:"varint,1,opt,name=principal_classification,json=principalClassification,proto3,enum=common.MSPPrincipal_Classification" json:"principal_classification,omitempty"` + // Principal completes the policy principal definition. For the default + // principal types, Principal can be either "Admin" or "Member". + // For the ByOrganizationUnit/ByIdentity values of Classification, + // PolicyPrincipal acquires its value from an organization unit or + // identity, respectively. + // For the Combined Classification type, the Principal is a marshalled + // CombinedPrincipal. + Principal []byte `protobuf:"bytes,2,opt,name=principal,proto3" json:"principal,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *MSPPrincipal) Reset() { *m = MSPPrincipal{} } +func (m *MSPPrincipal) String() string { return proto.CompactTextString(m) } +func (*MSPPrincipal) ProtoMessage() {} +func (*MSPPrincipal) Descriptor() ([]byte, []int) { + return fileDescriptor_msp_principal_9016cf1a8a7156cd, []int{0} +} +func (m *MSPPrincipal) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_MSPPrincipal.Unmarshal(m, b) +} +func (m *MSPPrincipal) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_MSPPrincipal.Marshal(b, m, deterministic) +} +func (dst *MSPPrincipal) XXX_Merge(src proto.Message) { + xxx_messageInfo_MSPPrincipal.Merge(dst, src) +} +func (m *MSPPrincipal) XXX_Size() int { + return xxx_messageInfo_MSPPrincipal.Size(m) +} +func (m *MSPPrincipal) XXX_DiscardUnknown() { + xxx_messageInfo_MSPPrincipal.DiscardUnknown(m) +} + +var xxx_messageInfo_MSPPrincipal proto.InternalMessageInfo + +func (m *MSPPrincipal) GetPrincipalClassification() MSPPrincipal_Classification { + if m != nil { + return m.PrincipalClassification + } + return MSPPrincipal_ROLE +} + +func (m *MSPPrincipal) GetPrincipal() []byte { + if m != nil { + return m.Principal + } + return nil +} + +// OrganizationUnit governs the organization of the Principal +// field of a policy principal when a specific organization unity members +// are to be defined within a policy principal. +type OrganizationUnit struct { + // MSPIdentifier represents the identifier of the MSP this organization unit + // refers to + MspIdentifier string `protobuf:"bytes,1,opt,name=msp_identifier,json=mspIdentifier,proto3" json:"msp_identifier,omitempty"` + // OrganizationUnitIdentifier defines the organizational unit under the + // MSP identified with MSPIdentifier + OrganizationalUnitIdentifier string `protobuf:"bytes,2,opt,name=organizational_unit_identifier,json=organizationalUnitIdentifier,proto3" json:"organizational_unit_identifier,omitempty"` + // CertifiersIdentifier is the hash of certificates chain of trust + // related to this organizational unit + CertifiersIdentifier []byte `protobuf:"bytes,3,opt,name=certifiers_identifier,json=certifiersIdentifier,proto3" json:"certifiers_identifier,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *OrganizationUnit) Reset() { *m = OrganizationUnit{} } +func (m *OrganizationUnit) String() string { return proto.CompactTextString(m) } +func (*OrganizationUnit) ProtoMessage() {} +func (*OrganizationUnit) Descriptor() ([]byte, []int) { + return fileDescriptor_msp_principal_9016cf1a8a7156cd, []int{1} +} +func (m *OrganizationUnit) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_OrganizationUnit.Unmarshal(m, b) +} +func (m *OrganizationUnit) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_OrganizationUnit.Marshal(b, m, deterministic) +} +func (dst *OrganizationUnit) XXX_Merge(src proto.Message) { + xxx_messageInfo_OrganizationUnit.Merge(dst, src) +} +func (m *OrganizationUnit) XXX_Size() int { + return xxx_messageInfo_OrganizationUnit.Size(m) +} +func (m *OrganizationUnit) XXX_DiscardUnknown() { + xxx_messageInfo_OrganizationUnit.DiscardUnknown(m) +} + +var xxx_messageInfo_OrganizationUnit proto.InternalMessageInfo + +func (m *OrganizationUnit) GetMspIdentifier() string { + if m != nil { + return m.MspIdentifier + } + return "" +} + +func (m *OrganizationUnit) GetOrganizationalUnitIdentifier() string { + if m != nil { + return m.OrganizationalUnitIdentifier + } + return "" +} + +func (m *OrganizationUnit) GetCertifiersIdentifier() []byte { + if m != nil { + return m.CertifiersIdentifier + } + return nil +} + +// MSPRole governs the organization of the Principal +// field of an MSPPrincipal when it aims to define one of the +// two dedicated roles within an MSP: Admin and Members. +type MSPRole struct { + // MSPIdentifier represents the identifier of the MSP this principal + // refers to + MspIdentifier string `protobuf:"bytes,1,opt,name=msp_identifier,json=mspIdentifier,proto3" json:"msp_identifier,omitempty"` + // MSPRoleType defines which of the available, pre-defined MSP-roles + // an identiy should posess inside the MSP with identifier MSPidentifier + Role MSPRole_MSPRoleType `protobuf:"varint,2,opt,name=role,proto3,enum=common.MSPRole_MSPRoleType" json:"role,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *MSPRole) Reset() { *m = MSPRole{} } +func (m *MSPRole) String() string { return proto.CompactTextString(m) } +func (*MSPRole) ProtoMessage() {} +func (*MSPRole) Descriptor() ([]byte, []int) { + return fileDescriptor_msp_principal_9016cf1a8a7156cd, []int{2} +} +func (m *MSPRole) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_MSPRole.Unmarshal(m, b) +} +func (m *MSPRole) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_MSPRole.Marshal(b, m, deterministic) +} +func (dst *MSPRole) XXX_Merge(src proto.Message) { + xxx_messageInfo_MSPRole.Merge(dst, src) +} +func (m *MSPRole) XXX_Size() int { + return xxx_messageInfo_MSPRole.Size(m) +} +func (m *MSPRole) XXX_DiscardUnknown() { + xxx_messageInfo_MSPRole.DiscardUnknown(m) +} + +var xxx_messageInfo_MSPRole proto.InternalMessageInfo + +func (m *MSPRole) GetMspIdentifier() string { + if m != nil { + return m.MspIdentifier + } + return "" +} + +func (m *MSPRole) GetRole() MSPRole_MSPRoleType { + if m != nil { + return m.Role + } + return MSPRole_MEMBER +} + +// MSPIdentityAnonymity can be used to enforce an identity to be anonymous or nominal. +type MSPIdentityAnonymity struct { + AnonymityType MSPIdentityAnonymity_MSPIdentityAnonymityType `protobuf:"varint,1,opt,name=anonymity_type,json=anonymityType,proto3,enum=common.MSPIdentityAnonymity_MSPIdentityAnonymityType" json:"anonymity_type,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *MSPIdentityAnonymity) Reset() { *m = MSPIdentityAnonymity{} } +func (m *MSPIdentityAnonymity) String() string { return proto.CompactTextString(m) } +func (*MSPIdentityAnonymity) ProtoMessage() {} +func (*MSPIdentityAnonymity) Descriptor() ([]byte, []int) { + return fileDescriptor_msp_principal_9016cf1a8a7156cd, []int{3} +} +func (m *MSPIdentityAnonymity) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_MSPIdentityAnonymity.Unmarshal(m, b) +} +func (m *MSPIdentityAnonymity) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_MSPIdentityAnonymity.Marshal(b, m, deterministic) +} +func (dst *MSPIdentityAnonymity) XXX_Merge(src proto.Message) { + xxx_messageInfo_MSPIdentityAnonymity.Merge(dst, src) +} +func (m *MSPIdentityAnonymity) XXX_Size() int { + return xxx_messageInfo_MSPIdentityAnonymity.Size(m) +} +func (m *MSPIdentityAnonymity) XXX_DiscardUnknown() { + xxx_messageInfo_MSPIdentityAnonymity.DiscardUnknown(m) +} + +var xxx_messageInfo_MSPIdentityAnonymity proto.InternalMessageInfo + +func (m *MSPIdentityAnonymity) GetAnonymityType() MSPIdentityAnonymity_MSPIdentityAnonymityType { + if m != nil { + return m.AnonymityType + } + return MSPIdentityAnonymity_NOMINAL +} + +// CombinedPrincipal governs the organization of the Principal +// field of a policy principal when principal_classification has +// indicated that a combined form of principals is required +type CombinedPrincipal struct { + // Principals refer to combined principals + Principals []*MSPPrincipal `protobuf:"bytes,1,rep,name=principals,proto3" json:"principals,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *CombinedPrincipal) Reset() { *m = CombinedPrincipal{} } +func (m *CombinedPrincipal) String() string { return proto.CompactTextString(m) } +func (*CombinedPrincipal) ProtoMessage() {} +func (*CombinedPrincipal) Descriptor() ([]byte, []int) { + return fileDescriptor_msp_principal_9016cf1a8a7156cd, []int{4} +} +func (m *CombinedPrincipal) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_CombinedPrincipal.Unmarshal(m, b) +} +func (m *CombinedPrincipal) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_CombinedPrincipal.Marshal(b, m, deterministic) +} +func (dst *CombinedPrincipal) XXX_Merge(src proto.Message) { + xxx_messageInfo_CombinedPrincipal.Merge(dst, src) +} +func (m *CombinedPrincipal) XXX_Size() int { + return xxx_messageInfo_CombinedPrincipal.Size(m) +} +func (m *CombinedPrincipal) XXX_DiscardUnknown() { + xxx_messageInfo_CombinedPrincipal.DiscardUnknown(m) +} + +var xxx_messageInfo_CombinedPrincipal proto.InternalMessageInfo + +func (m *CombinedPrincipal) GetPrincipals() []*MSPPrincipal { + if m != nil { + return m.Principals + } + return nil +} + +func init() { + proto.RegisterType((*MSPPrincipal)(nil), "common.MSPPrincipal") + proto.RegisterType((*OrganizationUnit)(nil), "common.OrganizationUnit") + proto.RegisterType((*MSPRole)(nil), "common.MSPRole") + proto.RegisterType((*MSPIdentityAnonymity)(nil), "common.MSPIdentityAnonymity") + proto.RegisterType((*CombinedPrincipal)(nil), "common.CombinedPrincipal") + proto.RegisterEnum("common.MSPPrincipal_Classification", MSPPrincipal_Classification_name, MSPPrincipal_Classification_value) + proto.RegisterEnum("common.MSPRole_MSPRoleType", MSPRole_MSPRoleType_name, MSPRole_MSPRoleType_value) + proto.RegisterEnum("common.MSPIdentityAnonymity_MSPIdentityAnonymityType", MSPIdentityAnonymity_MSPIdentityAnonymityType_name, MSPIdentityAnonymity_MSPIdentityAnonymityType_value) +} + +func init() { + proto.RegisterFile("msp/msp_principal.proto", fileDescriptor_msp_principal_9016cf1a8a7156cd) +} + +var fileDescriptor_msp_principal_9016cf1a8a7156cd = []byte{ + // 519 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x93, 0xdf, 0x6a, 0xdb, 0x30, + 0x14, 0xc6, 0xeb, 0xa4, 0x6b, 0x9b, 0x93, 0x3f, 0xa8, 0x22, 0xa5, 0x81, 0x95, 0x11, 0xbc, 0x0d, + 0x72, 0xe5, 0x40, 0xba, 0xed, 0x62, 0x77, 0x4e, 0x62, 0x86, 0x20, 0x96, 0x8d, 0xe3, 0x5c, 0xb4, + 0x94, 0x05, 0xc7, 0x51, 0x52, 0x81, 0x6d, 0x19, 0xdb, 0xbd, 0xf0, 0xde, 0x65, 0x6f, 0xb0, 0xcb, + 0x3d, 0xd5, 0x9e, 0x62, 0xd8, 0x6e, 0x12, 0x65, 0xeb, 0x60, 0x57, 0xf6, 0x39, 0xe7, 0xf7, 0x1d, + 0x1d, 0x49, 0x9f, 0xe0, 0x3a, 0x4c, 0xe3, 0x61, 0x98, 0xc6, 0xcb, 0x38, 0xe1, 0x91, 0xcf, 0x63, + 0x2f, 0xd0, 0xe2, 0x44, 0x64, 0x02, 0x9f, 0xf9, 0x22, 0x0c, 0x45, 0xa4, 0xfe, 0x52, 0xa0, 0x65, + 0xce, 0x6d, 0x7b, 0x57, 0xc6, 0x5f, 0xa1, 0xb7, 0x67, 0x97, 0x7e, 0xe0, 0xa5, 0x29, 0xdf, 0x70, + 0xdf, 0xcb, 0xb8, 0x88, 0x7a, 0x4a, 0x5f, 0x19, 0x74, 0x46, 0x6f, 0xb5, 0x4a, 0xab, 0xc9, 0x3a, + 0x6d, 0x72, 0x84, 0x3a, 0xd7, 0xfb, 0x26, 0xc7, 0x05, 0x7c, 0x03, 0x8d, 0x7d, 0xa9, 0x57, 0xeb, + 0x2b, 0x83, 0x96, 0x73, 0x48, 0xa8, 0x0f, 0xd0, 0xf9, 0x83, 0xbf, 0x80, 0x53, 0xc7, 0x9a, 0x19, + 0xe8, 0x04, 0x5f, 0xc1, 0xa5, 0xe5, 0x7c, 0xd1, 0x29, 0xb9, 0xd7, 0x5d, 0x62, 0xd1, 0xe5, 0x82, + 0x12, 0x17, 0x29, 0xb8, 0x05, 0x17, 0x64, 0x6a, 0x50, 0x97, 0xb8, 0x77, 0xa8, 0x86, 0xdb, 0xd0, + 0xd0, 0xa9, 0x45, 0xef, 0xcc, 0x22, 0xac, 0x17, 0xc5, 0x89, 0x65, 0x8e, 0x09, 0x35, 0xa6, 0xe8, + 0x54, 0xfd, 0xa9, 0x00, 0xb2, 0x92, 0xad, 0x17, 0xf1, 0x6f, 0x65, 0xf3, 0x45, 0xc4, 0x33, 0xfc, + 0x1e, 0x3a, 0xc5, 0x01, 0xf1, 0x35, 0x8b, 0x32, 0xbe, 0xe1, 0x2c, 0x29, 0xb7, 0xd9, 0x70, 0xda, + 0x61, 0x1a, 0x93, 0x7d, 0x12, 0x4f, 0xe1, 0x8d, 0x90, 0xa4, 0x5e, 0xb0, 0x7c, 0x8a, 0x78, 0x26, + 0xcb, 0x6a, 0xa5, 0xec, 0xe6, 0x98, 0x2a, 0x96, 0x90, 0xba, 0xdc, 0xc2, 0x95, 0xcf, 0x92, 0x2a, + 0x48, 0x65, 0x71, 0xbd, 0x3c, 0x89, 0xee, 0xa1, 0x78, 0x10, 0xa9, 0xdf, 0x15, 0x38, 0x37, 0xe7, + 0xb6, 0x23, 0x02, 0xf6, 0xbf, 0xd3, 0x0e, 0xe1, 0x34, 0x11, 0x01, 0x2b, 0x67, 0xea, 0x8c, 0x5e, + 0x4b, 0x37, 0x56, 0x74, 0xd9, 0x7d, 0xdd, 0x3c, 0x66, 0x4e, 0x09, 0xaa, 0x9f, 0xa1, 0x29, 0x25, + 0x31, 0xc0, 0x99, 0x69, 0x98, 0x63, 0xc3, 0x41, 0x27, 0xb8, 0x01, 0xaf, 0xf4, 0xa9, 0x49, 0x28, + 0x52, 0x8a, 0xf4, 0x64, 0x46, 0x0c, 0xea, 0xa2, 0x5a, 0x71, 0x31, 0xb6, 0x61, 0x38, 0xa8, 0xae, + 0xfe, 0x50, 0xa0, 0x6b, 0xce, 0xed, 0x6a, 0xf9, 0x2c, 0xd7, 0x23, 0x11, 0xe5, 0x21, 0xcf, 0x72, + 0xfc, 0x00, 0x1d, 0x6f, 0x17, 0x2c, 0xb3, 0x3c, 0x66, 0xcf, 0x0e, 0xfa, 0x28, 0xcd, 0xf3, 0x97, + 0xea, 0xc5, 0x64, 0x39, 0x69, 0xdb, 0x93, 0x43, 0xf5, 0x13, 0xf4, 0xfe, 0x85, 0xe2, 0x26, 0x9c, + 0x53, 0xcb, 0x24, 0x54, 0x9f, 0xa1, 0x93, 0x83, 0x27, 0xac, 0xc5, 0x1c, 0x29, 0x2a, 0x81, 0xcb, + 0x89, 0x08, 0x57, 0x3c, 0x62, 0xeb, 0x83, 0xed, 0x3f, 0x00, 0xec, 0x5d, 0x98, 0xf6, 0x94, 0x7e, + 0x7d, 0xd0, 0x1c, 0x75, 0x5f, 0x32, 0xba, 0x23, 0x71, 0x63, 0x1b, 0xde, 0x89, 0x64, 0xab, 0x3d, + 0xe6, 0x31, 0x4b, 0x02, 0xb6, 0xde, 0xb2, 0x44, 0xdb, 0x78, 0xab, 0x84, 0xfb, 0xd5, 0x2b, 0x4b, + 0x9f, 0x1b, 0xdc, 0x0f, 0xb6, 0x3c, 0x7b, 0x7c, 0x5a, 0x15, 0xe1, 0x50, 0x82, 0x87, 0x15, 0x3c, + 0xac, 0xe0, 0xe2, 0x9d, 0xae, 0xce, 0xca, 0xff, 0xdb, 0xdf, 0x01, 0x00, 0x00, 0xff, 0xff, 0x40, + 0x36, 0xd2, 0xf9, 0xb9, 0x03, 0x00, 0x00, +} diff --git a/chaincode/abac/go/vendor/github.com/hyperledger/fabric/protos/msp/msp_principal.proto b/chaincode/abac/go/vendor/github.com/hyperledger/fabric/protos/msp/msp_principal.proto new file mode 100644 index 00000000..972f0fe4 --- /dev/null +++ b/chaincode/abac/go/vendor/github.com/hyperledger/fabric/protos/msp/msp_principal.proto @@ -0,0 +1,153 @@ +/* +Copyright IBM Corp. 2016 All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + + +syntax = "proto3"; + +option go_package = "github.com/hyperledger/fabric/protos/msp"; +option java_package = "org.hyperledger.fabric.protos.common"; + +package common; + + +// msp_principal.proto contains proto messages defining the generalized +// MSP notion of identity called an MSPPrincipal. It is used as part of +// the chain configuration, in particular as the identity parameters to +// the configuration.proto file. This does not represent the MSP +// configuration for a chain, but is understood by MSPs + +// MSPPrincipal aims to represent an MSP-centric set of identities. +// In particular, this structure allows for definition of +// - a group of identities that are member of the same MSP +// - a group of identities that are member of the same organization unit +// in the same MSP +// - a group of identities that are administering a specific MSP +// - a specific identity +// Expressing these groups is done given two fields of the fields below +// - Classification, that defines the type of classification of identities +// in an MSP this principal would be defined on; Classification can take +// three values: +// (i) ByMSPRole: that represents a classification of identities within +// MSP based on one of the two pre-defined MSP rules, "member" and "admin" +// (ii) ByOrganizationUnit: that represents a classification of identities +// within MSP based on the organization unit an identity belongs to +// (iii)ByIdentity that denotes that MSPPrincipal is mapped to a single +// identity/certificate; this would mean that the Principal bytes +// message +message MSPPrincipal { + + enum Classification { + ROLE = 0; // Represents the one of the dedicated MSP roles, the + // one of a member of MSP network, and the one of an + // administrator of an MSP network + ORGANIZATION_UNIT = 1; // Denotes a finer grained (affiliation-based) + // groupping of entities, per MSP affiliation + // E.g., this can well be represented by an MSP's + // Organization unit + IDENTITY = 2; // Denotes a principal that consists of a single + // identity + ANONYMITY = 3; // Denotes a principal that can be used to enforce + // an identity to be anonymous or nominal. + COMBINED = 4; // Denotes a combined principal + } + + // Classification describes the way that one should process + // Principal. An Classification value of "ByOrganizationUnit" reflects + // that "Principal" contains the name of an organization this MSP + // handles. A Classification value "ByIdentity" means that + // "Principal" contains a specific identity. Default value + // denotes that Principal contains one of the groups by + // default supported by all MSPs ("admin" or "member"). + Classification principal_classification = 1; + + // Principal completes the policy principal definition. For the default + // principal types, Principal can be either "Admin" or "Member". + // For the ByOrganizationUnit/ByIdentity values of Classification, + // PolicyPrincipal acquires its value from an organization unit or + // identity, respectively. + // For the Combined Classification type, the Principal is a marshalled + // CombinedPrincipal. + bytes principal = 2; +} + + +// OrganizationUnit governs the organization of the Principal +// field of a policy principal when a specific organization unity members +// are to be defined within a policy principal. +message OrganizationUnit { + + // MSPIdentifier represents the identifier of the MSP this organization unit + // refers to + string msp_identifier = 1; + + // OrganizationUnitIdentifier defines the organizational unit under the + // MSP identified with MSPIdentifier + string organizational_unit_identifier = 2; + + // CertifiersIdentifier is the hash of certificates chain of trust + // related to this organizational unit + bytes certifiers_identifier = 3; +} + +// MSPRole governs the organization of the Principal +// field of an MSPPrincipal when it aims to define one of the +// two dedicated roles within an MSP: Admin and Members. +message MSPRole { + + // MSPIdentifier represents the identifier of the MSP this principal + // refers to + string msp_identifier = 1; + + enum MSPRoleType { + MEMBER = 0; // Represents an MSP Member + ADMIN = 1; // Represents an MSP Admin + CLIENT = 2; // Represents an MSP Client + PEER = 3; // Represents an MSP Peer + } + + // MSPRoleType defines which of the available, pre-defined MSP-roles + // an identiy should posess inside the MSP with identifier MSPidentifier + MSPRoleType role = 2; + +} + +// MSPIdentityAnonymity can be used to enforce an identity to be anonymous or nominal. +message MSPIdentityAnonymity { + + enum MSPIdentityAnonymityType { + NOMINAL = 0; // Represents a nominal MSP Identity + ANONYMOUS = 1; // Represents an anonymous MSP Identity + } + + MSPIdentityAnonymityType anonymity_type = 1; + +} + +// CombinedPrincipal governs the organization of the Principal +// field of a policy principal when principal_classification has +// indicated that a combined form of principals is required +message CombinedPrincipal { + + // Principals refer to combined principals + repeated MSPPrincipal principals = 1; +} + +// TODO: Bring msp.SerializedIdentity from fabric/msp/identities.proto here. Reason below. +// SerializedIdentity represents an serialized version of an identity; +// this consists of an MSP-identifier this identity would correspond to +// and the bytes of the actual identity. A serialized form of +// SerializedIdentity would govern "Principal" field of a PolicyPrincipal +// of classification "ByIdentity". diff --git a/chaincode/abac/go/vendor/github.com/pkg/errors/errors.go b/chaincode/abac/go/vendor/github.com/pkg/errors/errors.go index 842ee804..1963d86b 100644 --- a/chaincode/abac/go/vendor/github.com/pkg/errors/errors.go +++ b/chaincode/abac/go/vendor/github.com/pkg/errors/errors.go @@ -6,7 +6,7 @@ // return err // } // -// which applied recursively up the call stack results in error reports +// which when applied recursively up the call stack results in error reports // without context or debugging information. The errors package allows // programmers to add context to the failure path in their code in a way // that does not destroy the original value of the error. @@ -15,16 +15,17 @@ // // The errors.Wrap function returns a new error that adds context to the // original error by recording a stack trace at the point Wrap is called, -// and the supplied message. For example +// together with the supplied message. For example // // _, err := ioutil.ReadAll(r) // if err != nil { // return errors.Wrap(err, "read failed") // } // -// If additional control is required the errors.WithStack and errors.WithMessage -// functions destructure errors.Wrap into its component operations of annotating -// an error with a stack trace and an a message, respectively. +// If additional control is required, the errors.WithStack and +// errors.WithMessage functions destructure errors.Wrap into its component +// operations: annotating an error with a stack trace and with a message, +// respectively. // // Retrieving the cause of an error // @@ -38,7 +39,7 @@ // } // // can be inspected by errors.Cause. errors.Cause will recursively retrieve -// the topmost error which does not implement causer, which is assumed to be +// the topmost error that does not implement causer, which is assumed to be // the original cause. For example: // // switch err := errors.Cause(err).(type) { @@ -48,16 +49,16 @@ // // unknown error // } // -// causer interface is not exported by this package, but is considered a part -// of stable public API. +// Although the causer interface is not exported by this package, it is +// considered a part of its stable public interface. // // Formatted printing of errors // // All error values returned from this package implement fmt.Formatter and can -// be formatted by the fmt package. The following verbs are supported +// be formatted by the fmt package. The following verbs are supported: // // %s print the error. If the error has a Cause it will be -// printed recursively +// printed recursively. // %v see %s // %+v extended format. Each Frame of the error's StackTrace will // be printed in detail. @@ -65,13 +66,13 @@ // Retrieving the stack trace of an error or wrapper // // New, Errorf, Wrap, and Wrapf record a stack trace at the point they are -// invoked. This information can be retrieved with the following interface. +// invoked. This information can be retrieved with the following interface: // // type stackTracer interface { // StackTrace() errors.StackTrace // } // -// Where errors.StackTrace is defined as +// The returned errors.StackTrace type is defined as // // type StackTrace []Frame // @@ -85,8 +86,8 @@ // } // } // -// stackTracer interface is not exported by this package, but is considered a part -// of stable public API. +// Although the stackTracer interface is not exported by this package, it is +// considered a part of its stable public interface. // // See the documentation for Frame.Format for more details. package errors @@ -192,7 +193,7 @@ func Wrap(err error, message string) error { } // Wrapf returns an error annotating err with a stack trace -// at the point Wrapf is call, and the format specifier. +// at the point Wrapf is called, and the format specifier. // If err is nil, Wrapf returns nil. func Wrapf(err error, format string, args ...interface{}) error { if err == nil { @@ -220,6 +221,18 @@ func WithMessage(err error, message string) error { } } +// WithMessagef annotates err with the format specifier. +// If err is nil, WithMessagef returns nil. +func WithMessagef(err error, format string, args ...interface{}) error { + if err == nil { + return nil + } + return &withMessage{ + cause: err, + msg: fmt.Sprintf(format, args...), + } +} + type withMessage struct { cause error msg string diff --git a/chaincode/abac/go/vendor/vendor.json b/chaincode/abac/go/vendor/vendor.json index bd6bd571..9794848f 100644 --- a/chaincode/abac/go/vendor/vendor.json +++ b/chaincode/abac/go/vendor/vendor.json @@ -3,28 +3,34 @@ "ignore": "test", "package": [ { - "checksumSHA1": "WX1+2gktHcBmE9MGwFSGs7oqexU=", + "checksumSHA1": "GaJLoEuMGnP5ofXvuweAI4wx06U=", "path": "github.com/golang/protobuf/proto", - "revision": "bbd03ef6da3a115852eaf24c8a1c46aeb39aa175", - "revisionTime": "2018-02-02T18:43:18Z" + "revision": "1918e1ff6ffd2be7bed0553df8650672c3bfe80d", + "revisionTime": "2018-10-30T15:47:21Z" }, { - "checksumSHA1": "n+ZKx3gMoBi4t0fN84vzz0r2uCM=", - "path": "github.com/hyperledger/fabric/common/attrmgr", - "revision": "37d68a18f6afa156c1145900feaa16d2f558cfe5", - "revisionTime": "2018-02-26T20:04:44Z" + "checksumSHA1": "XGpUl1X+7ly1ski4Pc+N9ozfVv8=", + "path": "github.com/hyperledger/fabric/core/chaincode/shim/ext/attrmgr", + "revision": "60f968db8e6e2ebcf439391610e22250993d0a85", + "revisionTime": "2018-09-12T02:19:31Z" }, { - "checksumSHA1": "y8UGqcO/ZWyUDSrSy/ANg64vOvs=", - "path": "github.com/hyperledger/fabric/core/chaincode/lib/cid", - "revision": "37d68a18f6afa156c1145900feaa16d2f558cfe5", - "revisionTime": "2018-02-26T20:04:44Z" + "checksumSHA1": "vFuT7942CfsCcH9IG3zHmQ4d/oI=", + "path": "github.com/hyperledger/fabric/core/chaincode/shim/ext/cid", + "revision": "60f968db8e6e2ebcf439391610e22250993d0a85", + "revisionTime": "2018-09-12T02:19:31Z" }, { - "checksumSHA1": "ljd3FhYRJ91cLZz3wsH9BQQ2JbA=", + "checksumSHA1": "ZzWCzHsWRI/LAxhZYUMqVcIAsZQ=", + "path": "github.com/hyperledger/fabric/protos/msp", + "revision": "60f968db8e6e2ebcf439391610e22250993d0a85", + "revisionTime": "2018-09-12T02:19:31Z" + }, + { + "checksumSHA1": "DTy0iJ2w5C+FDsN9EnzfhNmvS+o=", "path": "github.com/pkg/errors", - "revision": "30136e27e2ac8d167177e8a583aa4c3fea5be833", - "revisionTime": "2018-01-27T01:58:12Z" + "revision": "059132a15dd08d6704c67711dae0cf35ab991756", + "revisionTime": "2018-10-23T23:59:46Z" } ], "rootPath": "github.com/hyperledger/fabric-samples/chaincode/abac/go" diff --git a/fabric-ca/README.md b/fabric-ca/README.md index 568a198e..dad58682 100755 --- a/fabric-ca/README.md +++ b/fabric-ca/README.md @@ -11,7 +11,7 @@ The Hyperledger Fabric CA sample demonstrates the following: container in which they are generated. * How to use Attribute-Based Access Control (ABAC). See - fabric-samples/chaincode/abac/abac.go and note the use of the *github.com/hyperledger/fabric/core/chaincode/lib/cid* package to extract + fabric-samples/chaincode/abac/abac.go and note the use of the *github.com/hyperledger/fabric/core/chaincode/shim/ext/cid* package to extract attributes from the invoker's identity. Only identities with the *abac.init* attribute value of *true* can successfully call the *Init* function to instantiate the chaincode. @@ -89,7 +89,7 @@ with a value of "true". Note further that the chaincode used by this sample requires this attribute be included in the certificate of the identity that invokes its Init function. See the chaincode at *fabric-samples/chaincode/abac/abac.go*). For more information on Attribute-Based Access Control (ABAC), see -https://github.com/hyperledger/fabric/blob/master/core/chaincode/lib/cid/README.md. +https://github.com/hyperledger/fabric/blob/master/core/chaincode/shim/ext/cid/README.md. 4. The orderer and peer containers are started. The naming of these containers is straight-forward as is their log files in the *data/logs* directory. From c05f172ba7d6f67b7cd8f2587175ee8bc6ad094a Mon Sep 17 00:00:00 2001 From: rameshthoomu Date: Thu, 25 Oct 2018 21:20:25 -0400 Subject: [PATCH 31/35] FAB-12608 Update pipeline script Change-Id: I788c3a6caaf967a4f2157428ee8264b969070acb Signed-off-by: rameshthoomu --- Jenkinsfile | 74 ++++++++++++++++--------- scripts/Jenkins_Scripts/CI_Script.sh | 80 +++++++++++----------------- scripts/Jenkins_Scripts/byfn_eyfn.sh | 60 +++++++++++++++------ 3 files changed, 125 insertions(+), 89 deletions(-) diff --git a/Jenkinsfile b/Jenkinsfile index a5836e26..8fcd2633 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -6,8 +6,21 @@ // Pipeline script for fabric-samples node ('hyp-x') { // trigger build on x86_64 node + timestamps { + try { def ROOTDIR = pwd() // workspace dir (/w/workspace/ + env.NODE_VER = "8.11.3" // NodeJs version + env.ARCH = "amd64" + env.VERSION = sh(returnStdout: true, script: 'curl -O https://raw.githubusercontent.com/hyperledger/fabric/master/Makefile && cat Makefile | grep "BASE_VERSION =" | cut -d "=" -f2').trim() + env.VERSION = "$VERSION" // BASE_VERSION from fabric Makefile + env.BASE_IMAGE_VER = sh(returnStdout: true, script: 'cat Makefile | grep BASEIMAGE_RELEASE= | cut -d "=" -f2').trim() // BASEIMAGE Version from fabric Makefile + env.IMAGE_TAG = "${ARCH}-${VERSION}-stable" // fabric latest stable version from nexus + env.PROJECT_VERSION = "${VERSION}-stable" + env.BASE_IMAGE_TAG = "${ARCH}-${BASE_IMAGE_VER}" //fabric baseimage version env.PROJECT_DIR = "gopath/src/github.com/hyperledger" + env.GOPATH = "$WORKSPACE/gopath" + env.PATH = "$GOPATH/bin:/usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin:~/npm/bin:/home/jenkins/.nvm/versions/node/v${NODE_VER}/bin:$PATH" + def failure_stage = "none" // delete working directory deleteDir() @@ -24,10 +37,11 @@ node ('hyp-x') { // trigger build on x86_64 node } catch (err) { failure_stage = "Fetch patchset" + currentBuild.result = 'FAILURE' throw err } - } -// clean environment and get env data + } + // clean environment and get env data stage("Clean Environment - Get Env Info") { try { dir("${ROOTDIR}/$PROJECT_DIR/fabric-samples/scripts/Jenkins_Scripts") { @@ -36,13 +50,15 @@ node ('hyp-x') { // trigger build on x86_64 node } catch (err) { failure_stage = "Clean Environment - Get Env Info" + currentBuild.result = 'FAILURE' throw err } - } + } - - // Pull Fabric Images + // Pull Third_party Images stage("Pull third_party images") { + // making the output color coded + wrap([$class: 'AnsiColorBuildWrapper', 'colorMapName': 'xterm']) { try { dir("${ROOTDIR}/$PROJECT_DIR/fabric-samples/scripts/Jenkins_Scripts") { sh './CI_Script.sh --pull_Thirdparty_Images' @@ -50,37 +66,33 @@ node ('hyp-x') { // trigger build on x86_64 node } catch (err) { failure_stage = "Pull third_party docker images" + currentBuild.result = 'FAILURE' throw err } + } } -// Pull Fabric Images - stage("Pull fabric images") { + // Pull Fabric, fabric-ca Images + stage("Pull Docker images") { + // making the output color coded + wrap([$class: 'AnsiColorBuildWrapper', 'colorMapName': 'xterm']) { try { dir("${ROOTDIR}/$PROJECT_DIR/fabric-samples/scripts/Jenkins_Scripts") { - sh './CI_Script.sh --pull_Fabric_Images' + sh './CI_Script.sh --pull_Docker_Images' } } catch (err) { - failure_stage = "Pull fabric docker images" + failure_stage = "Pull fabric, fabric-ca docker images" + currentBuild.result = 'FAILURE' throw err } + } } - // Pull Fabric-ca - stage("Pull fabric-ca images") { - try { - dir("${ROOTDIR}/$PROJECT_DIR/fabric-samples/scripts/Jenkins_Scripts") { - sh './CI_Script.sh --pull_Fabric_CA_Image' - } - } - catch (err) { - failure_stage = "Pull fabric-ca docker image" - throw err - } - } -// Run byfn, eyfn tests (default, custom channel, couchdb, nodejs chaincode, fabric-ca samples) + // Run byfn, eyfn tests (default, custom channel, couchdb, nodejs chaincode) stage("Run byfn_eyfn Tests") { + // making the output color coded + wrap([$class: 'AnsiColorBuildWrapper', 'colorMapName': 'xterm']) { try { dir("${ROOTDIR}/$PROJECT_DIR/fabric-samples/scripts/Jenkins_Scripts") { sh './CI_Script.sh --byfn_eyfn_Tests' @@ -88,10 +100,22 @@ node ('hyp-x') { // trigger build on x86_64 node } catch (err) { failure_stage = "byfn_eyfn_Tests" + currentBuild.result = 'FAILURE' throw err } + } } - stage("Archive Build artifacts") { - archiveArtifacts artifacts: '**/*.log' - } + } finally { + // Archive the artifacts + archiveArtifacts allowEmptyArchive: true, artifacts: '**/*.log' + // Sends notification to Rocket.Chat jenkins-robot channel + if (env.GERRIT_EVENT_TYPE == 'change-merged') { + if (currentBuild.result == 'FAILURE') { // Other values: SUCCESS, UNSTABLE + rocketSend channel: 'jenkins-robot', message: "Build Notification - STATUS: ${currentBuild.result} - BRANCH: ${env.GERRIT_BRANCH} - PROJECT: ${env.PROJECT} - (<${env.BUILD_URL}|Open>)" + } + } + } +// End Try block + } +// End Node block } diff --git a/scripts/Jenkins_Scripts/CI_Script.sh b/scripts/Jenkins_Scripts/CI_Script.sh index ab0d3aca..dd6cbc67 100755 --- a/scripts/Jenkins_Scripts/CI_Script.sh +++ b/scripts/Jenkins_Scripts/CI_Script.sh @@ -8,27 +8,8 @@ # exit on first error export BASE_FOLDER=$WORKSPACE/gopath/src/github.com/hyperledger -export PROJECT_VERSION=1.4.0-stable export NEXUS_URL=nexus3.hyperledger.org:10001 export ORG_NAME="hyperledger/fabric" -export NODE_VER=8.11.3 # Default nodejs version - -# Fetch baseimage version -curl -L https://raw.githubusercontent.com/hyperledger/fabric/master/Makefile > Makefile -export BASE_IMAGE_VER=`cat Makefile | grep BASEIMAGE_RELEASE= | cut -d "=" -f2` -echo "-----------> BASE_IMAGE_VER" $BASE_IMAGE_VER -export OS_VER=$(dpkg --print-architecture) -echo "-----------> OS_VER" $OS_VER -export BASE_IMAGE_TAG=$OS_VER-$BASE_IMAGE_VER - -# Fetch Go Version from fabric ci.properties file -curl -L https://raw.githubusercontent.com/hyperledger/fabric/master/ci.properties > ci.properties -export GO_VER=`cat ci.properties | grep GO_VER | cut -d "=" -f 2` -echo "-----------> GO_VER" $GO_VER - -# Published stable version from nexus -export STABLE_TAG=$OS_VER-$PROJECT_VERSION -echo "-----------> STABLE_TAG" $STABLE_TAG Parse_Arguments() { while [ $# -gt 0 ]; do @@ -39,11 +20,11 @@ Parse_Arguments() { --SetGopath) setGopath ;; - --pull_Fabric_Images) - pull_Fabric_Images + --pull_Docker_Images) + pull_Docker_Images ;; - --pull_Fabric_CA_Image) - pull_Fabric_CA_Image + --pull_Fabric_CA_Images) + pull_Fabric_CA_Images ;; --clean_Environment) clean_Environment @@ -117,55 +98,56 @@ env_Info() { docker info docker-compose version pgrep -a docker - docker images - docker ps -a } -setGopath() { - echo "-----------> set GOPATH" - echo - export GOPATH=$WORKSPACE/gopath - export JAVA_HOME=/usr/lib/jvm/java-1.8.0-openjdk-amd64 - export PATH=$GOROOT/bin:$GOPATH/bin:/usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin:~/npm/bin:/home/jenkins/.nvm/versions/node/v6.9.5/bin:/home/jenkins/.nvm/versions/node/v$NODE_VER/bin:$PATH - export GOROOT=/opt/go/go$GO_VER.linux.$OS_VER - export PATH=$GOROOT/bin:$PATH -} # Pull Thirdparty Docker images (Kafka, couchdb, zookeeper) pull_Thirdparty_Images() { + echo "------> BASE_IMAGE_TAG:" $BASE_IMAGE_TAG for IMAGES in kafka couchdb zookeeper; do - echo "-----------> Pull $IMAGE image" + echo "-----------> Pull $IMAGES image" echo - docker pull $ORG_NAME-$IMAGES:$BASE_IMAGE_TAG - docker tag $ORG_NAME-$IMAGES:$BASE_IMAGE_TAG $ORG_NAME-$IMAGES + docker pull $ORG_NAME-$IMAGES:${BASE_IMAGE_TAG} > /dev/null 2>&1 + if [ $? -ne 0 ]; then + echo -e "\033[31m FAILED to pull docker images" "\033[0m" + exit 1 + fi + docker tag $ORG_NAME-$IMAGES:${BASE_IMAGE_TAG} $ORG_NAME-$IMAGES done echo docker images | grep hyperledger/fabric } # pull fabric images from nexus -pull_Fabric_Images() { - setGopath fabric # set gopath +pull_Docker_Images() { + pull_Fabric_CA_Image for IMAGES in peer orderer tools ccenv; do echo "-----------> pull $IMAGES image" echo - docker pull $NEXUS_URL/$ORG_NAME-$IMAGES:$STABLE_TAG - docker tag $NEXUS_URL/$ORG_NAME-$IMAGES:$STABLE_TAG $ORG_NAME-$IMAGES - docker tag $NEXUS_URL/$ORG_NAME-$IMAGES:$STABLE_TAG $ORG_NAME-$IMAGES:$STABLE_TAG - docker rmi -f $NEXUS_URL/$ORG_NAME-$IMAGES:$STABLE_TAG + docker pull $NEXUS_URL/$ORG_NAME-$IMAGES:$IMAGE_TAG > /dev/null 2>&1 + if [ $? -ne 0 ]; then + echo -e "\033[31m FAILED to pull docker images" "\033[0m" + exit 1 + fi + docker tag $NEXUS_URL/$ORG_NAME-$IMAGES:$IMAGE_TAG $ORG_NAME-$IMAGES + docker tag $NEXUS_URL/$ORG_NAME-$IMAGES:$IMAGE_TAG $ORG_NAME-$IMAGES:$IMAGE_TAG + docker rmi -f $NEXUS_URL/$ORG_NAME-$IMAGES:$IMAGE_TAG done echo docker images | grep hyperledger/fabric } # pull fabric-ca images from nexus pull_Fabric_CA_Image() { - echo - setGopath fabric-ca + echo "------> IMAGE_TAG:" $IMAGE_TAG for IMAGES in ca ca-peer ca-orderer ca-tools; do echo "-----------> pull $IMAGES image" echo - docker pull $NEXUS_URL/$ORG_NAME-$IMAGES:$STABLE_TAG - docker tag $NEXUS_URL/$ORG_NAME-$IMAGES:$STABLE_TAG $ORG_NAME-$IMAGES - docker tag $NEXUS_URL/$ORG_NAME-$IMAGES:$STABLE_TAG $ORG_NAME-$IMAGES:$STABLE_TAG - docker rmi -f $NEXUS_URL/$ORG_NAME-$IMAGES:$STABLE_TAG + docker pull $NEXUS_URL/$ORG_NAME-$IMAGES:$IMAGE_TAG > /dev/null 2>&1 + if [ $? -ne 0 ]; then + echo -e "\033[31m FAILED to pull docker images" "\033[0m" + exit 1 + fi + docker tag $NEXUS_URL/$ORG_NAME-$IMAGES:$IMAGE_TAG $ORG_NAME-$IMAGES + docker tag $NEXUS_URL/$ORG_NAME-$IMAGES:$IMAGE_TAG $ORG_NAME-$IMAGES:$IMAGE_TAG + docker rmi -f $NEXUS_URL/$ORG_NAME-$IMAGES:$IMAGE_TAG done echo docker images | grep hyperledger/fabric-ca diff --git a/scripts/Jenkins_Scripts/byfn_eyfn.sh b/scripts/Jenkins_Scripts/byfn_eyfn.sh index 103907a5..3b1bc23b 100755 --- a/scripts/Jenkins_Scripts/byfn_eyfn.sh +++ b/scripts/Jenkins_Scripts/byfn_eyfn.sh @@ -5,25 +5,55 @@ # SPDX-License-Identifier: Apache-2.0 # -ARCH=$(dpkg --print-architecture) -echo "-----------> ARCH" $ARCH +# docker container list +CONTAINER_LIST=(peer0.org1 peer1.org1 peer0.org2 peer1.org2 peer0.org3 peer1.org3 orderer) +COUCHDB_CONTAINER_LIST=(couchdb0 couchdb1 couchdb2 couchdb3 couchdb4 couchdb5) + MARCH=$(uname -s|tr '[:upper:]' '[:lower:]') echo "-----------> MARCH" $MARCH -VERSION=1.4.0 -MVN_METADATA=$(echo "https://nexus.hyperledger.org/content/repositories/releases/org/hyperledger/fabric/hyperledger-fabric-$VERSION-stable/maven-metadata.xml") +echo "-----------> PROJECT_VERSION:" $PROJECT_VERSION +MVN_METADATA=$(echo "https://nexus.hyperledger.org/content/repositories/releases/org/hyperledger/fabric/hyperledger-fabric-$PROJECT_VERSION/maven-metadata.xml") curl -L "$MVN_METADATA" > maven-metadata.xml RELEASE_TAG=$(cat maven-metadata.xml | grep release) COMMIT=$(echo $RELEASE_TAG | awk -F - '{ print $4 }' | cut -d "<" -f1) -echo "-----------> BASE_VERSION = $VERSION" +echo "-----------> COMMIT = $COMMIT" cd $BASE_FOLDER/fabric-samples || exit -curl https://nexus.hyperledger.org/content/repositories/releases/org/hyperledger/fabric/hyperledger-fabric-$VERSION-stable/$MARCH-$ARCH.$VERSION-stable-$COMMIT/hyperledger-fabric-$VERSION-stable-$MARCH-$ARCH.$VERSION-stable-$COMMIT.tar.gz | tar xz +curl https://nexus.hyperledger.org/content/repositories/releases/org/hyperledger/fabric/hyperledger-fabric-$PROJECT_VERSION/$MARCH-$ARCH.$PROJECT_VERSION-$COMMIT/hyperledger-fabric-$PROJECT_VERSION-$MARCH-$ARCH.$PROJECT_VERSION-$COMMIT.tar.gz | tar xz + +if [ $? -ne 0 ]; then + echo -e "\033[31m FAILED to download binaries" "\033[0m" + exit 1 +fi cd first-network || exit export PATH=gopath/src/github.com/hyperledger/fabric-samples/bin:$PATH -err_Check() { +logs() { + +# Create Logs directory +mkdir -p $WORKSPACE/Docker_Container_Logs + +for CONTAINER in ${CONTAINER_LIST[*]}; do + docker logs $CONTAINER.example.com >& $WORKSPACE/Docker_Container_Logs/$CONTAINER-$1.log + echo +done +} + +if [ ! -z $2 ]; then + + for CONTAINER in ${COUCHDB_CONTAINER_LIST[*]}; do + docker logs $CONTAINER >& $WORKSPACE/Docker_Container_Logs/$CONTAINER-$1.log + echo + done +fi + +copy_logs() { + +# Call logs function +logs $2 $3 + if [ $1 != 0 ]; then - echo "Error: -----------> $2 test case failed" + echo -e "\033[31m $2 test case is FAILED" "\033[0m" exit 1 fi } @@ -32,32 +62,32 @@ fi echo "#################################################################" echo y | ./byfn.sh -m down echo y | ./byfn.sh -m up -t 60 - err_Check $? default-channel + copy_logs $? default-channel echo y | ./eyfn.sh -m up -t 60 - err_Check $? default-channel + copy_logs $? default-channel echo y | ./eyfn.sh -m down echo echo "############### BYFN,EYFN CUSTOM CHANNEL WITH COUCHDB TEST ##############" echo "#########################################################################" echo y | ./byfn.sh -m up -c custom-channel-couchdb -s couchdb -t 75 -d 15 - err_Check $? custom-channel-couch couchdb + copy_logs $? custom-channel-couch couchdb echo y | ./eyfn.sh -m up -c custom-channel-couchdb -s couchdb -t 75 -d 15 - err_Check $? custom-channel-couch + copy_logs $? custom-channel-couch echo y | ./eyfn.sh -m down echo echo "############### BYFN,EYFN WITH NODE Chaincode. TEST ################" echo "####################################################################" echo y | ./byfn.sh -m up -l node -t 60 - err_Check $? default-channel-node + copy_logs $? default-channel-node echo y | ./eyfn.sh -m up -l node -t 60 - err_Check $? default-channel-node + copy_logs $? default-channel-node echo y | ./eyfn.sh -m down echo "############### FABRIC-CA SAMPLES TEST ########################" echo "###############################################################" cd $WORKSPACE/gopath/src/github.com/hyperledger/fabric-samples/fabric-ca ./start.sh - err_Check $? fabric-ca + copy_logs $? fabric-ca ./stop.sh From fd6e2c41c901a6b4521416b3e470c287778341c6 Mon Sep 17 00:00:00 2001 From: Daisuke IIZUKA Date: Tue, 30 Oct 2018 07:46:55 +0000 Subject: [PATCH 32/35] [FAB-12703] Fix misspelling "lauches" iFix misspelling "lauches" to "launches". Change-Id: I4605262356631e421db7a8902b1b324e8d17ca25 Signed-off-by: Daisuke IIZUKA --- balance-transfer/README.md | 2 +- balance-transfer/typescript/README.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/balance-transfer/README.md b/balance-transfer/README.md index 7d551d25..0b31ec74 100644 --- a/balance-transfer/README.md +++ b/balance-transfer/README.md @@ -68,7 +68,7 @@ cd fabric-samples/balance-transfer ``` -* This lauches the required network on your local machine +* This launches the required network on your local machine * Installs the fabric-client and fabric-ca-client node modules * And, starts the node app on PORT 4000 diff --git a/balance-transfer/typescript/README.md b/balance-transfer/typescript/README.md index abbfb12f..bbfdc1f8 100644 --- a/balance-transfer/typescript/README.md +++ b/balance-transfer/typescript/README.md @@ -43,7 +43,7 @@ cd fabric-samples/balance-transfer/typescript ``` This performs the following steps: -* lauches the required network on your local machine +* launches the required network on your local machine * installs the fabric-client and fabric-ca-client node modules * starts the node app on PORT 4000 From e67fcf14a39bf0e01b44e4ba56bd129e105de44c Mon Sep 17 00:00:00 2001 From: Anthony O'Dowd Date: Wed, 24 Oct 2018 15:32:54 +0100 Subject: [PATCH 33/35] FAB-12322 Update commercial-paper sample Change-Id: I235cb62df492b7713bb1c355b7457f679903bd34 Signed-off-by: Anthony O'Dowd --- commercial-paper/.gitignore | 8 + commercial-paper/application/application.js | 76 ------ commercial-paper/contract/index.js | 7 - commercial-paper/contract/lib/cpcontract.js | 113 --------- commercial-paper/contract/lib/cpstate.js | 148 ------------ commercial-paper/contract/lib/utils.js | 34 --- .../digibank/application/.eslintrc.js | 37 +++ .../digibank/application/addToWallet.js | 45 ++++ .../organization/digibank/application/buy.js | 102 ++++++++ .../digibank/application/package.json | 20 ++ .../digibank/application/redeem.js | 101 ++++++++ .../configuration/cli/docker-compose.yml | 38 +++ .../configuration/cli/monitordocker.sh | 25 ++ .../digibank}/contract/.editorconfig | 0 .../digibank}/contract/.eslintignore | 0 .../digibank}/contract/.eslintrc.js | 0 .../digibank}/contract/.npmignore | 0 .../organization/digibank/contract/index.js | 8 + .../digibank/contract/ledger-api/state.js | 98 ++++++++ .../contract/ledger-api/statelist.js} | 54 ++--- .../digibank}/contract/lib/paper.js | 67 ++---- .../digibank}/contract/lib/papercontract.js | 102 ++++---- .../digibank/contract/lib/paperlist.js | 33 +++ .../digibank}/contract/package.json | 20 +- .../digibank}/contract/test/contract.js | 0 .../digibank/gateway/networkConnection.yaml | 129 ++++++++++ .../digibank/gateway/papernetConnection.yaml} | 32 +-- .../magnetocorp/application/.eslintrc.js | 37 +++ .../magnetocorp/application/addToWallet.js | 45 ++++ .../magnetocorp/application/issue.js | 102 ++++++++ .../magnetocorp/application/package.json | 20 ++ .../configuration/cli/docker-compose.yml | 38 +++ .../configuration/cli/monitordocker.sh | 25 ++ .../magnetocorp/contract/.editorconfig | 16 ++ .../magnetocorp/contract/.eslintignore | 5 + .../magnetocorp/contract/.eslintrc.js | 37 +++ .../magnetocorp/contract/.npmignore | 77 ++++++ .../magnetocorp/contract/index.js | 8 + .../magnetocorp/contract/ledger-api/state.js | 98 ++++++++ .../contract/ledger-api/statelist.js | 68 ++++++ .../magnetocorp/contract/lib/paper.js | 102 ++++++++ .../magnetocorp/contract/lib/papercontract.js | 156 ++++++++++++ .../magnetocorp/contract/lib/paperlist.js | 33 +++ .../magnetocorp/contract/package.json | 49 ++++ .../magnetocorp/contract/test/contract.js | 41 ++++ .../gateway/networkConnection.yaml | 129 ++++++++++ .../gateway/papernetConnection.yaml | 225 ++++++++++++++++++ 47 files changed, 2086 insertions(+), 522 deletions(-) create mode 100644 commercial-paper/.gitignore delete mode 100644 commercial-paper/application/application.js delete mode 100644 commercial-paper/contract/index.js delete mode 100644 commercial-paper/contract/lib/cpcontract.js delete mode 100644 commercial-paper/contract/lib/cpstate.js delete mode 100644 commercial-paper/contract/lib/utils.js create mode 100644 commercial-paper/organization/digibank/application/.eslintrc.js create mode 100644 commercial-paper/organization/digibank/application/addToWallet.js create mode 100644 commercial-paper/organization/digibank/application/buy.js create mode 100644 commercial-paper/organization/digibank/application/package.json create mode 100644 commercial-paper/organization/digibank/application/redeem.js create mode 100644 commercial-paper/organization/digibank/configuration/cli/docker-compose.yml create mode 100755 commercial-paper/organization/digibank/configuration/cli/monitordocker.sh rename commercial-paper/{ => organization/digibank}/contract/.editorconfig (100%) rename commercial-paper/{ => organization/digibank}/contract/.eslintignore (100%) rename commercial-paper/{ => organization/digibank}/contract/.eslintrc.js (100%) rename commercial-paper/{ => organization/digibank}/contract/.npmignore (100%) create mode 100644 commercial-paper/organization/digibank/contract/index.js create mode 100644 commercial-paper/organization/digibank/contract/ledger-api/state.js rename commercial-paper/{contract/lib/ledgerutils.js => organization/digibank/contract/ledger-api/statelist.js} (55%) rename commercial-paper/{ => organization/digibank}/contract/lib/paper.js (55%) rename commercial-paper/{ => organization/digibank}/contract/lib/papercontract.js (53%) create mode 100644 commercial-paper/organization/digibank/contract/lib/paperlist.js rename commercial-paper/{ => organization/digibank}/contract/package.json (62%) rename commercial-paper/{ => organization/digibank}/contract/test/contract.js (100%) create mode 100644 commercial-paper/organization/digibank/gateway/networkConnection.yaml rename commercial-paper/{application/gateway/connectionProfile.yaml => organization/digibank/gateway/papernetConnection.yaml} (86%) create mode 100644 commercial-paper/organization/magnetocorp/application/.eslintrc.js create mode 100644 commercial-paper/organization/magnetocorp/application/addToWallet.js create mode 100644 commercial-paper/organization/magnetocorp/application/issue.js create mode 100644 commercial-paper/organization/magnetocorp/application/package.json create mode 100644 commercial-paper/organization/magnetocorp/configuration/cli/docker-compose.yml create mode 100755 commercial-paper/organization/magnetocorp/configuration/cli/monitordocker.sh create mode 100755 commercial-paper/organization/magnetocorp/contract/.editorconfig create mode 100644 commercial-paper/organization/magnetocorp/contract/.eslintignore create mode 100644 commercial-paper/organization/magnetocorp/contract/.eslintrc.js create mode 100644 commercial-paper/organization/magnetocorp/contract/.npmignore create mode 100644 commercial-paper/organization/magnetocorp/contract/index.js create mode 100644 commercial-paper/organization/magnetocorp/contract/ledger-api/state.js create mode 100644 commercial-paper/organization/magnetocorp/contract/ledger-api/statelist.js create mode 100644 commercial-paper/organization/magnetocorp/contract/lib/paper.js create mode 100644 commercial-paper/organization/magnetocorp/contract/lib/papercontract.js create mode 100644 commercial-paper/organization/magnetocorp/contract/lib/paperlist.js create mode 100644 commercial-paper/organization/magnetocorp/contract/package.json create mode 100644 commercial-paper/organization/magnetocorp/contract/test/contract.js create mode 100644 commercial-paper/organization/magnetocorp/gateway/networkConnection.yaml create mode 100644 commercial-paper/organization/magnetocorp/gateway/papernetConnection.yaml diff --git a/commercial-paper/.gitignore b/commercial-paper/.gitignore new file mode 100644 index 00000000..14c40052 --- /dev/null +++ b/commercial-paper/.gitignore @@ -0,0 +1,8 @@ +organization/magnetocorp/application/node_modules/ +organization/magnetocorp/contract/node_modules/ +organization/magnetocorp/identity/user/ +organization/digibank/application/node_modules/ +organization/digibank/contract/node_modules/ +organization/digibank/identity/user/ +package-lock.json +.vscode diff --git a/commercial-paper/application/application.js b/commercial-paper/application/application.js deleted file mode 100644 index af11620c..00000000 --- a/commercial-paper/application/application.js +++ /dev/null @@ -1,76 +0,0 @@ -/* -SPDX-License-Identifier: Apache-2.0 -*/ - -/* - * This application has 6 basic steps: - * 1. Select an identity from a wallet - * 2. Connect to network gateway - * 3. Access PaperNet network - * 4. Construct request to issue commercial paper - * 5. Submit transaction - * 6. Process response - */ - -'use strict'; - -// Bring key classes into scope, most importantly Fabric SDK network class -const file = require("fs"); -const yaml = require('js-yaml'); -const { FileSystemWallet, Gateway } = require('fabric-network'); -const { CommercialPaper } = require('./paper.js'); - -// A wallet stores a collection of identities for use -const wallet = new FileSystemWallet('./wallet'); - -// A gateway defines the peers used to access Fabric networks -const gateway = new Gateway(); - -// Main try/catch/finally block -try { - - // Load connection profile; will be used to locate a gateway - connectionProfile = yaml.safeLoad(file.readFileSync('./gateway/connectionProfile.yaml', 'utf8')); - - // Set connection options; use 'admin' identity from application wallet - let connectionOptions = { - identity: 'isabella.the.issuer@magnetocorp.com', - wallet: wallet, - commitTimeout: 100, - strategy: MSPID_SCOPE_ANYFORTX, - commitNotifyStrategy: WAIT_FOR_ALL_CHANNEL_PEER - } - - // Connect to gateway using application specified parameters - await gateway.connect(connectionProfile, connectionOptions); - - console.log('Connected to Fabric gateway.') - - // Get addressability to PaperNet network - const network = await gateway.getNetwork('PaperNet'); - - // Get addressability to commercial paper contract - const contract = await network.getContract('papercontract', 'org.papernet.commercialpaper'); - - console.log('Submit commercial paper issue transaction.') - - // issue commercial paper - const response = await contract.submitTransaction('issue', 'MagnetoCorp', '00001', '2020-05-31', '2020-11-30', '5000000'); - - let paper = CommercialPaper.deserialize(response); - - console.log(`${paper.issuer} commercial paper : ${paper.paperNumber} successfully issued for value ${paper.faceValue}`); - - console.log('Transaction complete.') - -} catch (error) { - - console.log(`Error processing transaction. ${error}`); - -} finally { - - // Disconnect from the gateway - console.log('Disconnect from Fabric gateway.') - gateway.disconnect(); - -} \ No newline at end of file diff --git a/commercial-paper/contract/index.js b/commercial-paper/contract/index.js deleted file mode 100644 index ddc4f2c6..00000000 --- a/commercial-paper/contract/index.js +++ /dev/null @@ -1,7 +0,0 @@ -/* -SPDX-License-Identifier: Apache-2.0 -*/ - -'use strict'; - -module.exports.contracts = require('./lib/cpcontract.js'); diff --git a/commercial-paper/contract/lib/cpcontract.js b/commercial-paper/contract/lib/cpcontract.js deleted file mode 100644 index ed793fd1..00000000 --- a/commercial-paper/contract/lib/cpcontract.js +++ /dev/null @@ -1,113 +0,0 @@ -/* -SPDX-License-Identifier: Apache-2.0 -*/ - -'use strict'; - -// Smart contract API brought into scope -const {Contract} = require('fabric-contract-api'); - -// Commercial paper classes brought into scope -const {CommercialPaper, CommercialPaperList} = require('./cpstate.js'); - -/** - * Define the commercial paper smart contract extending Fabric Contract class - */ -class CommercialPaperContract extends Contract { - - /** - * Each smart contract can have a unique namespace; useful when multiple - * smart contracts per file. - * Use transaction context (ctx) to access list of all commercial papers. - */ - constructor() { - super('org.papernet.commercialpaper'); - - this.setBeforeFn = (ctx)=>{ - ctx.cpList = new CommercialPaperList(ctx, 'COMMERCIALPAPER'); - return ctx; - }; - } - - /** - * Issue commercial paper - * @param {TxContext} ctx the transaction context - * @param {String} issuer commercial paper issuer - * @param {Integer} paperNumber paper number for this issuer - * @param {String} issueDateTime paper issue date - * @param {String} maturityDateTime paper maturity date - * @param {Integer} faceValue face value of paper - */ - async issue(ctx, issuer, paperNumber, issueDateTime, maturityDateTime, faceValue) { - - let cp = new CommercialPaper(issuer, paperNumber, issueDateTime, maturityDateTime, faceValue); - - // {issuer:"MagnetoCorp", paperNumber:"00001", "May31 2020", "Nov 30 2020", "5M USD"} - - await ctx.cpList.addPaper(cp); - } - - /** - * Buy commercial paper - * @param {TxContext} ctx the transaction context - * @param {String} issuer commercial paper issuer - * @param {Integer} paperNumber paper number for this issuer - * @param {String} currentOwner current owner of paper - * @param {String} newOwner new owner of paper - * @param {Integer} price price paid for this paper - * @param {String} purchaseDateTime time paper was purchased (i.e. traded) - */ - async buy(ctx, issuer, paperNumber, currentOwner, newOwner, price, purchaseDateTime) { - - let cpKey = CommercialPaper.createKey(issuer, paperNumber); - let cp = await ctx.cpList.getPaper(cpKey); - - if (cp.getOwner() !== currentOwner) { - throw new Error('Paper '+issuer+paperNumber+' is not owned by '+currentOwner); - } - // First buy moves state from ISSUED to TRADING - if (cp.isIssued()) { - cp.setTrading(); - } - // Check paper is TRADING, not REDEEMED - if (cp.IsTrading()) { - cp.setOwner(newOwner); - } else { - throw new Error('Paper '+issuer+paperNumber+' is not trading. Current state = '+cp.getCurrentState()); - } - - await ctx.cpList.updatePaper(cp); - } - - /** - * Redeem commercial paper - * @param {TxContext} ctx the transaction context - * @param {String} issuer commercial paper issuer - * @param {Integer} paperNumber paper number for this issuer - * @param {String} redeemingOwner redeeming owner of paper - * @param {String} redeemDateTime time paper was redeemed - */ - async redeem(ctx, issuer, paperNumber, redeemingOwner, redeemDateTime) { - - let cpKey = CommercialPaper.createKey(issuer, paperNumber); - let cp = await ctx.cpList.getPaper(cpKey); - - // Check paper is TRADING, not REDEEMED - if (cp.IsRedeemed()) { - throw new Error('Paper '+issuer+paperNumber+' already redeemed'); - } - - // Verify that the redeemer owns the commercial paper before redeeming it - if (cp.getOwner() === redeemingOwner) { - cp.setOwner(cp.getIssuer()); - cp.setRedeemed(); - } else { - throw new Error('Redeeming owner does not own paper'+issuer+paperNumber); - } - - await ctx.cpList.updatePaper(cp); - } - -} - -module.exports = CommericalPaperContract; diff --git a/commercial-paper/contract/lib/cpstate.js b/commercial-paper/contract/lib/cpstate.js deleted file mode 100644 index ad5222cd..00000000 --- a/commercial-paper/contract/lib/cpstate.js +++ /dev/null @@ -1,148 +0,0 @@ -/* -SPDX-License-Identifier: Apache-2.0 -*/ - -'use strict'; - -// Helpful utilities class -const Utils = require('./utils.js'); - -// Enumeration of commercial paper state values -const cpState = { - ISSUED: 1, - TRADING: 2, - REDEEMED: 3 -}; - -/** - * CommercialPaper class defines a commercial paper state - */ -class CommercialPaper { - - /** - * Construct a commercial paper. Initial state is issued. - */ - constructor(issuer, paperNumber, issueDateTime, maturityDateTime, faceValue) { - this.issuer = issuer; - this.paperNumber = paperNumber; - this.owner = issuer; - this.issueDateTime = issueDateTime; - this.maturityDateTime = maturityDateTime; - this.faceValue = faceValue; - this.currentState = cpState.ISSUED; - this.key = CommercialPaper.createKey(issuer, paperNumber); - } - - /** - * The commercial paper is uniquely identified by its key. - * The key is a simple composite of issuer and paper number as strings. - */ - static createKey(issuer, paperNumber) { - return JSON.stringify(issuer) + JSON.stringify(paperNumber); - } - - /** - * Basic getters and setters - */ - getKey() { - return this.key; - } - - getIssuer() { - return this.issuer; - } - - setIssuer(newIssuer) { - this.issuer = newIssuer; - } - - getOwner() { - return this.owner; - } - - setOwner(newOwner) { - this.owner = newOwner; - } - - /** - * Useful methods to encapsulate commercial paper states - */ - setTrading() { - this.currentState = cpState.TRADING; - } - - setRedeemed() { - this.currentState = cpState.REDEEMED; - } - - isTrading() { - return this.currentState === cpState.TRADING; - } - - isRedeemed() { - return this.currentState === cpState.REDEEMED; - } - -} - -/** - * CommercialPaperList provides a virtual container to access all - * commercial papers. Each paper has unique key which associates it - * with the container, rather than the container containing a link to - * the paper. This is important in Fabric becuase it minimizes - * collisions for parallel transactions on different papers. - */ -class CommercialPaperList { - - /** - * For this sample, it is sufficient to create a commercial paper list - * using a fixed container prefix. The transaction context is saved to - * access Fabric APIs when required. - */ - constructor(ctx, prefix) { - this.api = ctx.stub; - this.prefix = prefix; - } - - /** - * Add a paper to the list. Creates a new state in worldstate with - * appropriate composite key. Note that paper defines its own key. - * Paper object is serialized before writing. - */ - async addPaper(cp) { - let key = this.api.createCompositeKey(this.prefix, [cp.getKey()]); - let data = Utils.serialize(cp); - await this.api.putState(key, data); - } - - /** - * Get a paper from the list using issuer and paper number. Forms composite - * keys to retrieve data from world state. State data is deserialized - * into paper object before being returned. - */ - async getPaper(key) { - let key = this.api.createCompositeKey(this.prefix, [key]); - let data = await this.api.getState(key); - let cp = Utils.deserialize(data); - return cp; - } - - /** - * Update a paper in the list. Puts the new state in world state with - * appropriate composite key. Note that paper defines its own key. - * Paper object is serialized before writing. Logic is very similar to - * addPaper() but kept separate becuase it is semantically distinct, and - * may change. - */ - async updatePaper(cp) { - let key = this.api.createCompositeKey(this.prefix, [cp.getKey()]); - let data = Utils.serialize(cp); - await this.api.putState(key, data); - } - -} - -module.exports = { - CommercialPaper, - CommercialPaperList -}; diff --git a/commercial-paper/contract/lib/utils.js b/commercial-paper/contract/lib/utils.js deleted file mode 100644 index 2a2c08ad..00000000 --- a/commercial-paper/contract/lib/utils.js +++ /dev/null @@ -1,34 +0,0 @@ -/* -SPDX-License-Identifier: Apache-2.0 -*/ - -'use strict'; - -/** - * Utility class for data, object mapulation, e.g. serialization - */ - -class Utils { - - /** - * Convert object to buffer containing JSON data serialization - * Typically used before putState() ledger API - * @param {Object} object object to serialize - * @return {buffer} buffer with the data to store - */ - static serialize(object){ - return Buffer.from(JSON.stringify(object)); - } - - /** - * Deserialize object, i.e. Covert serialized data to JSON object - * Typically used after getState() ledger API - * @param {Object} data object to deserialize - * @return {json} json with the data to store - */ - static deserialize(data){ - return JSON.parse(data); - } -} - -module.exports = Utils; diff --git a/commercial-paper/organization/digibank/application/.eslintrc.js b/commercial-paper/organization/digibank/application/.eslintrc.js new file mode 100644 index 00000000..22fbefc8 --- /dev/null +++ b/commercial-paper/organization/digibank/application/.eslintrc.js @@ -0,0 +1,37 @@ +/* +SPDX-License-Identifier: Apache-2.0 +*/ + +module.exports = { + env: { + node: true, + mocha: true + }, + parserOptions: { + ecmaVersion: 8, + sourceType: 'script' + }, + extends: "eslint:recommended", + rules: { + indent: ['error', 4], + 'linebreak-style': ['error', 'unix'], + quotes: ['error', 'single'], + semi: ['error', 'always'], + 'no-unused-vars': ['error', { args: 'none' }], + 'no-console': 'off', + curly: 'error', + eqeqeq: 'error', + 'no-throw-literal': 'error', + strict: 'error', + 'no-var': 'error', + 'dot-notation': 'error', + 'no-tabs': 'error', + 'no-trailing-spaces': 'error', + 'no-use-before-define': 'error', + 'no-useless-call': 'error', + 'no-with': 'error', + 'operator-linebreak': 'error', + yoda: 'error', + 'quote-props': ['error', 'as-needed'] + } +}; \ No newline at end of file diff --git a/commercial-paper/organization/digibank/application/addToWallet.js b/commercial-paper/organization/digibank/application/addToWallet.js new file mode 100644 index 00000000..b2b4415f --- /dev/null +++ b/commercial-paper/organization/digibank/application/addToWallet.js @@ -0,0 +1,45 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + */ + +'use strict'; + +// Bring key classes into scope, most importantly Fabric SDK network class +const fs = require('fs'); +const { FileSystemWallet, X509WalletMixin } = require('fabric-network'); +const path = require('path'); + +const fixtures = path.resolve(__dirname, '../../../../basic-network'); + +// A wallet stores a collection of identities +const wallet = new FileSystemWallet('../identity/user/balaji/wallet'); + +async function main() { + + // Main try/catch block + try { + + // Identity to credentials to be stored in the wallet + const credPath = path.join(fixtures, '/crypto-config/peerOrganizations/org1.example.com/users/Admin@org1.example.com'); + const cert = fs.readFileSync(path.join(credPath, '/msp/signcerts/Admin@org1.example.com-cert.pem')).toString(); + const key = fs.readFileSync(path.join(credPath, '/msp/keystore/cd96d5260ad4757551ed4a5a991e62130f8008a0bf996e4e4b84cd097a747fec_sk')).toString(); + + // Load credentials into wallet + const identityLabel = 'Admin@org1.example.com'; + const identity = X509WalletMixin.createIdentity('Org1MSP', cert, key); + + await wallet.import(identityLabel, identity); + + } catch (error) { + console.log(`Error adding to wallet. ${error}`); + console.log(error.stack); + } +} + +main().then(() => { + console.log('done'); +}).catch((e) => { + console.log(e); + console.log(e.stack); + process.exit(-1); +}); \ No newline at end of file diff --git a/commercial-paper/organization/digibank/application/buy.js b/commercial-paper/organization/digibank/application/buy.js new file mode 100644 index 00000000..45267dc0 --- /dev/null +++ b/commercial-paper/organization/digibank/application/buy.js @@ -0,0 +1,102 @@ +/* +SPDX-License-Identifier: Apache-2.0 +*/ + +/* + * This application has 6 basic steps: + * 1. Select an identity from a wallet + * 2. Connect to network gateway + * 3. Access PaperNet network + * 4. Construct request to issue commercial paper + * 5. Submit transaction + * 6. Process response + */ + +'use strict'; + +// Bring key classes into scope, most importantly Fabric SDK network class +const fs = require('fs'); +const yaml = require('js-yaml'); +const { FileSystemWallet, Gateway } = require('fabric-network'); +const CommercialPaper = require('../contract/lib/paper.js'); + +// A wallet stores a collection of identities for use +const wallet = new FileSystemWallet('../identity/user/balaji/wallet'); + +// Main program function +async function main() { + + // A gateway defines the peers used to access Fabric networks + const gateway = new Gateway(); + + // Main try/catch block + try { + + // Specify userName for network access + // const userName = 'isabella.issuer@magnetocorp.com'; + const userName = 'Admin@org1.example.com'; + + // Load connection profile; will be used to locate a gateway + let connectionProfile = yaml.safeLoad(fs.readFileSync('../gateway/networkConnection.yaml', 'utf8')); + + // Set connection options; identity and wallet + let connectionOptions = { + identity: userName, + wallet: wallet, + discovery: { enabled:false, asLocalhost: true } + + }; + + // Connect to gateway using application specified parameters + console.log('Connect to Fabric gateway.'); + + await gateway.connect(connectionProfile, connectionOptions); + + // Access PaperNet network + console.log('Use network channel: mychannel.'); + + const network = await gateway.getNetwork('mychannel'); + + // Get addressability to commercial paper contract + console.log('Use org.papernet.commercialpaper smart contract.'); + + const contract = await network.getContract('papercontract', 'org.papernet.commercialpaper'); + + // buy commercial paper + console.log('Submit commercial paper buy transaction.'); + + const buyResponse = await contract.submitTransaction('buy', 'MagnetoCorp', '00001', 'MagnetoCorp', 'DigiBank', '4900000', '2020-05-31'); + + // process response + console.log('Process buy transaction response.'); + + let paper = CommercialPaper.fromBuffer(buyResponse); + + console.log(`${paper.issuer} commercial paper : ${paper.paperNumber} successfully purchased by ${paper.owner}`); + console.log('Transaction complete.'); + + } catch (error) { + + console.log(`Error processing transaction. ${error}`); + console.log(error.stack); + + } finally { + + // Disconnect from the gateway + console.log('Disconnect from Fabric gateway.') + gateway.disconnect(); + + } +} +main().then(() => { + + console.log('Buy program complete.'); + +}).catch((e) => { + + console.log('Buy program exception.'); + console.log(e); + console.log(e.stack); + process.exit(-1); + +}); \ No newline at end of file diff --git a/commercial-paper/organization/digibank/application/package.json b/commercial-paper/organization/digibank/application/package.json new file mode 100644 index 00000000..b31c669a --- /dev/null +++ b/commercial-paper/organization/digibank/application/package.json @@ -0,0 +1,20 @@ +{ + "name": "nodejs", + "version": "1.0.0", + "description": "", + "main": "buy.js", + "scripts": { + "test": "rm -rf _idwallet && node addToWallet.js && node buy.js" + }, + "keywords": [], + "author": "", + "license": "ISC", + "dependencies": { + "fabric-network": "^1.4.0-beta", + "fabric-client": "^1.4.0-beta", + "js-yaml": "^3.12.0" + }, + "devDependencies": { + "eslint": "^5.6.0" + } +} diff --git a/commercial-paper/organization/digibank/application/redeem.js b/commercial-paper/organization/digibank/application/redeem.js new file mode 100644 index 00000000..3f3ffd45 --- /dev/null +++ b/commercial-paper/organization/digibank/application/redeem.js @@ -0,0 +1,101 @@ +/* +SPDX-License-Identifier: Apache-2.0 +*/ + +/* + * This application has 6 basic steps: + * 1. Select an identity from a wallet + * 2. Connect to network gateway + * 3. Access PaperNet network + * 4. Construct request to issue commercial paper + * 5. Submit transaction + * 6. Process response + */ + +'use strict'; + +// Bring key classes into scope, most importantly Fabric SDK network class +const fs = require('fs'); +const yaml = require('js-yaml'); +const { FileSystemWallet, Gateway } = require('fabric-network'); +const CommercialPaper = require('../contract/lib/paper.js'); + +// A wallet stores a collection of identities for use +const wallet = new FileSystemWallet('../identity/user/balaji/wallet'); + +// Main program function +async function main() { + + // A gateway defines the peers used to access Fabric networks + const gateway = new Gateway(); + + // Main try/catch block + try { + + // Specify userName for network access + // const userName = 'isabella.issuer@magnetocorp.com'; + const userName = 'Admin@org1.example.com'; + + // Load connection profile; will be used to locate a gateway + let connectionProfile = yaml.safeLoad(fs.readFileSync('../gateway/networkConnection.yaml', 'utf8')); + + // Set connection options; identity and wallet + let connectionOptions = { + identity: userName, + wallet: wallet, + discovery: { enabled:false, asLocalhost: true } + }; + + // Connect to gateway using application specified parameters + console.log('Connect to Fabric gateway.'); + + await gateway.connect(connectionProfile, connectionOptions); + + // Access PaperNet network + console.log('Use network channel: mychannel.'); + + const network = await gateway.getNetwork('mychannel'); + + // Get addressability to commercial paper contract + console.log('Use org.papernet.commercialpaper smart contract.'); + + const contract = await network.getContract('papercontract', 'org.papernet.commercialpaper'); + + // redeem commercial paper + console.log('Submit commercial paper redeem transaction.'); + + const redeemResponse = await contract.submitTransaction('redeem', 'MagnetoCorp', '00001', 'DigiBank', '2020-11-30'); + + // process response + console.log('Process redeem transaction response.'); + + let paper = CommercialPaper.fromBuffer(redeemResponse); + + console.log(`${paper.issuer} commercial paper : ${paper.paperNumber} successfully redeemed with ${paper.owner}`); + console.log('Transaction complete.'); + + } catch (error) { + + console.log(`Error processing transaction. ${error}`); + console.log(error.stack); + + } finally { + + // Disconnect from the gateway + console.log('Disconnect from Fabric gateway.') + gateway.disconnect(); + + } +} +main().then(() => { + + console.log('Redeem program complete.'); + +}).catch((e) => { + + console.log('Redeem program exception.'); + console.log(e); + console.log(e.stack); + process.exit(-1); + +}); \ No newline at end of file diff --git a/commercial-paper/organization/digibank/configuration/cli/docker-compose.yml b/commercial-paper/organization/digibank/configuration/cli/docker-compose.yml new file mode 100644 index 00000000..554bdda3 --- /dev/null +++ b/commercial-paper/organization/digibank/configuration/cli/docker-compose.yml @@ -0,0 +1,38 @@ +# +# Copyright IBM Corp All Rights Reserved +# +# SPDX-License-Identifier: Apache-2.0 +# +version: '2' + +networks: + basic: + external: + name: net_basic + +services: + cliDigiBank: + container_name: cliDigiBank + image: hyperledger/fabric-tools + tty: true + environment: + - GOPATH=/opt/gopath + - CORE_VM_ENDPOINT=unix:///host/var/run/docker.sock + - CORE_LOGGING_LEVEL=info + - CORE_PEER_ID=cli + - CORE_PEER_ADDRESS=peer0.org1.example.com:7051 + - CORE_PEER_LOCALMSPID=Org1MSP + - CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp + - CORE_CHAINCODE_KEEPALIVE=10 + working_dir: /opt/gopath/src/github.com/hyperledger/fabric/peer + command: /bin/bash + volumes: + - /var/run/:/host/var/run/ + - ./../../../../organization/digibank:/opt/gopath/src/github.com/ + - ./../../../../../basic-network/crypto-config:/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ + networks: + - basic + #depends_on: + # - orderer.example.com + # - peer0.org1.example.com + # - couchdb diff --git a/commercial-paper/organization/digibank/configuration/cli/monitordocker.sh b/commercial-paper/organization/digibank/configuration/cli/monitordocker.sh new file mode 100755 index 00000000..355acf07 --- /dev/null +++ b/commercial-paper/organization/digibank/configuration/cli/monitordocker.sh @@ -0,0 +1,25 @@ +#!/bin/bash + +# This script uses the logspout and http stream tools to let you watch the docker containers +# in action. +# +# More information at https://github.com/gliderlabs/logspout/tree/master/httpstream + +if [ -z "$1" ]; then + DOCKER_NETWORK=basicnetwork_basic +else + DOCKER_NETWORK="$1" +fi + +echo Starting monitoring on all containers on the network ${DOCKER_NETWORK} + +docker kill logspout 2> /dev/null 1>&2 || true +docker rm logspout 2> /dev/null 1>&2 || true + +docker run -d --name="logspout" \ + --volume=/var/run/docker.sock:/var/run/docker.sock \ + --publish=127.0.0.1:8000:80 \ + --network ${DOCKER_NETWORK} \ + gliderlabs/logspout +sleep 3 +curl http://127.0.0.1:8000/logs \ No newline at end of file diff --git a/commercial-paper/contract/.editorconfig b/commercial-paper/organization/digibank/contract/.editorconfig similarity index 100% rename from commercial-paper/contract/.editorconfig rename to commercial-paper/organization/digibank/contract/.editorconfig diff --git a/commercial-paper/contract/.eslintignore b/commercial-paper/organization/digibank/contract/.eslintignore similarity index 100% rename from commercial-paper/contract/.eslintignore rename to commercial-paper/organization/digibank/contract/.eslintignore diff --git a/commercial-paper/contract/.eslintrc.js b/commercial-paper/organization/digibank/contract/.eslintrc.js similarity index 100% rename from commercial-paper/contract/.eslintrc.js rename to commercial-paper/organization/digibank/contract/.eslintrc.js diff --git a/commercial-paper/contract/.npmignore b/commercial-paper/organization/digibank/contract/.npmignore similarity index 100% rename from commercial-paper/contract/.npmignore rename to commercial-paper/organization/digibank/contract/.npmignore diff --git a/commercial-paper/organization/digibank/contract/index.js b/commercial-paper/organization/digibank/contract/index.js new file mode 100644 index 00000000..b957b5e3 --- /dev/null +++ b/commercial-paper/organization/digibank/contract/index.js @@ -0,0 +1,8 @@ +/* +SPDX-License-Identifier: Apache-2.0 +*/ + +'use strict'; + +const cpcontract = require('./lib/papercontract.js'); +module.exports.contracts = [cpcontract]; \ No newline at end of file diff --git a/commercial-paper/organization/digibank/contract/ledger-api/state.js b/commercial-paper/organization/digibank/contract/ledger-api/state.js new file mode 100644 index 00000000..df2fbe57 --- /dev/null +++ b/commercial-paper/organization/digibank/contract/ledger-api/state.js @@ -0,0 +1,98 @@ +/* +SPDX-License-Identifier: Apache-2.0 +*/ + +'use strict'; + +/** + * State class. States have a class, unique key, and a lifecycle current state + * the current state is determined by the specific subclass + */ +class State { + + /** + * @param {String|Object} class An indentifiable class of the instance + * @param {keyParts[]} elements to pull together to make a key for the objects + */ + constructor(stateClass, keyParts) { + this.class = stateClass; + this.key = State.makeKey(keyParts); + this.currentState = null; + } + + getClass() { + return this.class; + } + + getKey() { + return this.key; + } + + getSplitKey(){ + return State.splitKey(this.key); + } + + getCurrentState(){ + return this.currentState; + } + + serialize() { + return State.serialize(this); + } + + /** + * Convert object to buffer containing JSON data serialization + * Typically used before putState()ledger API + * @param {Object} JSON object to serialize + * @return {buffer} buffer with the data to store + */ + static serialize(object) { + return Buffer.from(JSON.stringify(object)); + } + + /** + * Deserialize object into one of a set of supported JSON classes + * i.e. Covert serialized data to JSON object + * Typically used after getState() ledger API + * @param {data} data to deserialize into JSON object + * @param (supportedClasses) the set of classes data can be serialized to + * @return {json} json with the data to store + */ + static deserialize(data, supportedClasses) { + let json = JSON.parse(data.toString()); + let objClass = supportedClasses[json.class]; + if (!objClass) { + throw new Error(`Unknown class of ${json.class}`); + } + let object = new (objClass)(json); + + return object; + } + + /** + * Deserialize object into specific object class + * Typically used after getState() ledger API + * @param {data} data to deserialize into JSON object + * @return {json} json with the data to store + */ + static deserializeClass(data, objClass) { + let json = JSON.parse(data.toString()); + let object = new (objClass)(json); + return object; + } + + /** + * Join the keyParts to make a unififed string + * @param (String[]) keyParts + */ + static makeKey(keyParts) { + return keyParts.map(part => JSON.stringify(part)).join(':'); + } + + static splitKey(key){ + return key.split(':'); + } + +} + +module.exports = State; \ No newline at end of file diff --git a/commercial-paper/contract/lib/ledgerutils.js b/commercial-paper/organization/digibank/contract/ledger-api/statelist.js similarity index 55% rename from commercial-paper/contract/lib/ledgerutils.js rename to commercial-paper/organization/digibank/contract/ledger-api/statelist.js index b18f60ea..3c39671a 100644 --- a/commercial-paper/contract/lib/ledgerutils.js +++ b/commercial-paper/organization/digibank/contract/ledger-api/statelist.js @@ -3,32 +3,7 @@ SPDX-License-Identifier: Apache-2.0 */ 'use strict'; - -/** - * Utility class for data, object mapulation, e.g. serialization - */ -class Utils { - - /** - * Convert object to buffer containing JSON data serialization - * Typically used before putState()ledger API - * @param {Object} JSON object to serialize - * @return {buffer} buffer with the data to store - */ - static serialize(object) { - return Buffer.from(JSON.stringify(object)); - } - - /** - * Deserialize object, i.e. Covert serialized data to JSON object - * Typically used after getState() ledger API - * @param {data} data to deserialize into JSON object - * @return {json} json with the data to store - */ - static deserialize(data) { - return JSON.parse(data); - } -} +const State = require('./state.js'); /** * StateList provides a named virtual container for a set of ledger states. @@ -44,6 +19,8 @@ class StateList { constructor(ctx, listName) { this.ctx = ctx; this.name = listName; + this.supportedClasses = {}; + } /** @@ -52,8 +29,8 @@ class StateList { * State object is serialized before writing. */ async addState(state) { - let key = this.ctx.stub.createCompositeKey(this.name, [state.getKey()]); - let data = Utils.serialize(state); + let key = this.ctx.stub.createCompositeKey(this.name, state.getSplitKey()); + let data = State.serialize(state); await this.ctx.stub.putState(key, data); } @@ -62,10 +39,10 @@ class StateList { * keys to retrieve state from world state. State data is deserialized * into JSON object before being returned. */ - async getState([keys]) { - let key = this.ctx.stub.createCompositeKey(this.name, [keys]); - let data = await this.ctx.stub.getState(key); - let state = Utils.deserialize(data); + async getState(key) { + let ledgerKey = this.ctx.stub.createCompositeKey(this.name, State.splitKey(key)); + let data = await this.ctx.stub.getState(ledgerKey); + let state = State.deserialize(data, this.supportedClasses); return state; } @@ -76,13 +53,16 @@ class StateList { * addState() but kept separate becuase it is semantically distinct. */ async updateState(state) { - let key = this.ctx.stub.createCompositeKey(this.name, [state.getKey()]); - let data = Utils.serialize(state); + let key = this.ctx.stub.createCompositeKey(this.name, state.getSplitKey()); + let data = State.serialize(state); await this.ctx.stub.putState(key, data); } + /** Stores the class for future deserialization */ + use(stateClass) { + this.supportedClasses[stateClass.getClass()] = stateClass; + } + } -module.exports = { - StateList -}; +module.exports = StateList; \ No newline at end of file diff --git a/commercial-paper/contract/lib/paper.js b/commercial-paper/organization/digibank/contract/lib/paper.js similarity index 55% rename from commercial-paper/contract/lib/paper.js rename to commercial-paper/organization/digibank/contract/lib/paper.js index db770cfb..9d76adac 100644 --- a/commercial-paper/contract/lib/paper.js +++ b/commercial-paper/organization/digibank/contract/lib/paper.js @@ -4,6 +4,9 @@ SPDX-License-Identifier: Apache-2.0 'use strict'; +// Utility class for ledger state +const State = require('./../ledger-api/state.js'); + // Enumerate commercial paper state values const cpState = { ISSUED: 1, @@ -11,45 +14,15 @@ const cpState = { REDEEMED: 3 }; -/** - * State class. States have a type, unique key, and a lifecycle current state - */ -class State { - constructor(type, [keyParts]) { - this.type = JSON.stringify(type); - this.key = makeKey([keyParts]); - this.currentState = null; - } - - getType() { - return this.type; - } - - static makeKey([keyParts]) { - return keyParts.map(part => JSON.stringify(part)).join(''); - } - - getKey() { - return this.key; - } - -} - /** * CommercialPaper class extends State class * Class will be used by application and smart contract to define a paper */ class CommercialPaper extends State { - constructor(issuer, paperNumber, issueDateTime, maturityDateTime, faceValue) { - super(`org.papernet.commercialpaper`, [issuer, paperNumber]); - - this.issuer = issuer; - this.paperNumber = paperNumber; - this.owner = issuer; - this.issueDateTime = issueDateTime; - this.maturityDateTime = maturityDateTime; - this.faceValue = faceValue; + constructor(obj) { + super(CommercialPaper.getClass(), [obj.issuer, obj.paperNumber]); + Object.assign(this, obj); } /** @@ -98,20 +71,32 @@ class CommercialPaper extends State { return this.currentState === cpState.REDEEMED; } - /** - * Serialize/deserialize commercial paper - **/ + static fromBuffer(buffer) { + return CommercialPaper.deserialize(Buffer.from(JSON.parse(buffer))); + } - serialize() { + toBuffer() { return Buffer.from(JSON.stringify(this)); } + /** + * Deserialize a state data to commercial paper + * @param {Buffer} data to form back into the object + */ static deserialize(data) { - return Object.create(new CommercialPaper, JSON.parse(data)); + return State.deserializeClass(data, CommercialPaper); } + /** + * Factory method to create a commercial paper object + */ + static createInstance(issuer, paperNumber, issueDateTime, maturityDateTime, faceValue) { + return new CommercialPaper({ issuer, paperNumber, issueDateTime, maturityDateTime, faceValue }); + } + + static getClass() { + return 'org.papernet.commercialpaper'; + } } -module.exports = { - CommercialPaper, -}; +module.exports = CommercialPaper; diff --git a/commercial-paper/contract/lib/papercontract.js b/commercial-paper/organization/digibank/contract/lib/papercontract.js similarity index 53% rename from commercial-paper/contract/lib/papercontract.js rename to commercial-paper/organization/digibank/contract/lib/papercontract.js index a4963279..c0b132bf 100644 --- a/commercial-paper/contract/lib/papercontract.js +++ b/commercial-paper/organization/digibank/contract/lib/papercontract.js @@ -8,25 +8,25 @@ SPDX-License-Identifier: Apache-2.0 const { Contract, Context } = require('fabric-contract-api'); // PaperNet specifc classes -const { CommercialPaper } = require('./paper.js'); - -// Utility classes -const { StateList } = require('./ledgerutils.js'); +const CommercialPaper = require('./paper.js'); +const PaperList = require('./paperlist.js'); /** - * Define custom context for commercial paper by extending Fabric Context class + * A custom context provides easy access to list of all commercial papers */ -class CommericalPaperContext extends Context { +class CommercialPaperContext extends Context { constructor() { - // All papers held ins a list of Fabric states - this.cpList = new StateList(this, 'org.papernet.commercialpaperlist'); + super(); + // All papers are held in a list of papers + this.paperList = new PaperList(this); } } /** * Define commercial paper smart contract by extending Fabric Contract class + * */ class CommercialPaperContract extends Contract { @@ -35,20 +35,27 @@ class CommercialPaperContract extends Contract { super('org.papernet.commercialpaper'); } - // This method is called when a smart contract is instantiated - // Often used to set up the ledger main transactions are called - instantiate() { - + /** + * Define a custom context for commercial paper + */ + createContext() { + return new CommercialPaperContext(); } - // A custom context provides easy access to the list of commercial papers - createContext() { - return new CommericalPaperContext(); + /** + * Instantiate to perform any setup of the ledger that might be required. + * @param {Context} ctx the transaction context + */ + async instantiate(ctx) { + // No implementation required with this example + // It could be where data migration is performed, if necessary + console.log('Instantiate the contract'); } /** * Issue commercial paper - * @param {TxContext} ctx the transaction context + * + * @param {Context} ctx the transaction context * @param {String} issuer commercial paper issuer * @param {Integer} paperNumber paper number for this issuer * @param {String} issueDateTime paper issue date @@ -57,20 +64,26 @@ class CommercialPaperContract extends Contract { */ async issue(ctx, issuer, paperNumber, issueDateTime, maturityDateTime, faceValue) { - let cp = new CommercialPaper(issuer, paperNumber, issueDateTime, maturityDateTime, faceValue); + // create an instance of the paper + let paper = CommercialPaper.createInstance(issuer, paperNumber, issueDateTime, maturityDateTime, faceValue); // Smart contract, rather than paper, moves paper into ISSUED state - cp.setIssued(); + paper.setIssued(); + + // Newly issued paper is owned by the issuer + paper.setOwner(issuer); // Add the paper to the list of all similar commercial papers in the ledger world state - await ctx.cpList.addState(cp); + await ctx.paperList.addPaper(paper); - return cp.serialize(); + // Must return a serialized paper to caller of smart contract + return paper.toBuffer(); } /** * Buy commercial paper - * @param {TxContext} ctx the transaction context + * + * @param {Context} ctx the transaction context * @param {String} issuer commercial paper issuer * @param {Integer} paperNumber paper number for this issuer * @param {String} currentOwner current owner of paper @@ -80,31 +93,36 @@ class CommercialPaperContract extends Contract { */ async buy(ctx, issuer, paperNumber, currentOwner, newOwner, price, purchaseDateTime) { - let cpKey = CommercialPaper.makeKey([issuer, paperNumber]); + // Retrieve the current paper using key fields provided + let paperKey = CommercialPaper.makeKey([issuer, paperNumber]); + let paper = await ctx.paperList.getPaper(paperKey); - let cp = await ctx.cpList.getState(cpKey); - - if (cp.getOwner() !== currentOwner) { + // Validate current owner + if (paper.getOwner() !== currentOwner) { throw new Error('Paper ' + issuer + paperNumber + ' is not owned by ' + currentOwner); } + // First buy moves state from ISSUED to TRADING - if (cp.isIssued()) { - cp.setTrading(); + if (paper.isIssued()) { + paper.setTrading(); } + // Check paper is not already REDEEMED - if (cp.IsTrading()) { - cp.setOwner(newOwner); + if (paper.isTrading()) { + paper.setOwner(newOwner); } else { throw new Error('Paper ' + issuer + paperNumber + ' is not trading. Current state = ' + cp.getCurrentState()); } - await ctx.cpList.updateState(cp); - return cp.deserialize(); + // Update the paper + await ctx.paperList.updatePaper(paper); + return paper.toBuffer(); } /** * Redeem commercial paper - * @param {TxContext} ctx the transaction context + * + * @param {Context} ctx the transaction context * @param {String} issuer commercial paper issuer * @param {Integer} paperNumber paper number for this issuer * @param {String} redeemingOwner redeeming owner of paper @@ -112,27 +130,27 @@ class CommercialPaperContract extends Contract { */ async redeem(ctx, issuer, paperNumber, redeemingOwner, redeemDateTime) { - let cpKey = CommercialPaper.makeKey([issuer, paperNumber]); + let paperKey = CommercialPaper.makeKey([issuer, paperNumber]); - let cp = await ctx.cpList.getState(cpKey); + let paper = await ctx.paperList.getPaper(paperKey); - // Check paper is TRADING, not REDEEMED - if (cp.IsRedeemed()) { + // Check paper is not REDEEMED + if (paper.isRedeemed()) { throw new Error('Paper ' + issuer + paperNumber + ' already redeemed'); } // Verify that the redeemer owns the commercial paper before redeeming it - if (cp.getOwner() === redeemingOwner) { - cp.setOwner(cp.getIssuer()); - cp.setRedeemed(); + if (paper.getOwner() === redeemingOwner) { + paper.setOwner(paper.getIssuer()); + paper.setRedeemed(); } else { throw new Error('Redeeming owner does not own paper' + issuer + paperNumber); } - await ctx.cpList.updateState(cp); - return cp.serialize(); + await ctx.paperList.updatePaper(paper); + return paper.toBuffer(); } } -module.exports = CommericalPaperContract; +module.exports = CommercialPaperContract; diff --git a/commercial-paper/organization/digibank/contract/lib/paperlist.js b/commercial-paper/organization/digibank/contract/lib/paperlist.js new file mode 100644 index 00000000..ac5d7183 --- /dev/null +++ b/commercial-paper/organization/digibank/contract/lib/paperlist.js @@ -0,0 +1,33 @@ +/* +SPDX-License-Identifier: Apache-2.0 +*/ + +'use strict'; + +// Utility class for collections of ledger states -- a state list +const StateList = require('./../ledger-api/statelist.js'); + +const CommercialPaper = require('./paper.js'); + +class PaperList extends StateList { + + constructor(ctx) { + super(ctx, 'org.papernet.commercialpaperlist'); + this.use(CommercialPaper); + } + + async addPaper(paper) { + return this.addState(paper); + } + + async getPaper(paperKey) { + return this.getState(paperKey); + } + + async updatePaper(paper) { + return this.updateState(paper); + } +} + + +module.exports = PaperList; \ No newline at end of file diff --git a/commercial-paper/contract/package.json b/commercial-paper/organization/digibank/contract/package.json similarity index 62% rename from commercial-paper/contract/package.json rename to commercial-paper/organization/digibank/contract/package.json index 5741509f..6d79d096 100644 --- a/commercial-paper/contract/package.json +++ b/commercial-paper/organization/digibank/contract/package.json @@ -1,7 +1,8 @@ { - "name": "smart-contract", + "name": "papernet-js", "version": "0.0.1", - "description": "Smart Contract", + "description": "Papernet Contract", + "main": "index.js", "engines": { "node": ">=8", "npm": ">=5" @@ -9,22 +10,25 @@ "scripts": { "lint": "eslint .", "pretest": "npm run lint", - "test": "nyc mocha --recursive", - "start": "startChaincode" + "test": "nyc mocha test --recursive", + "start": "fabric-chaincode-node start", + "mocha": "mocha test --recursive" }, "engineStrict": true, - "author": "Anthony ODowd", + "author": "hyperledger", "license": "Apache-2.0", "dependencies": { - "fabric-shim": "unstable", - "fabric-contract-api": "unstable" + "fabric-contract-api": "^1.4.0-snapshot.17", + "fabric-shim": "^1.4.0-snapshot.27" }, "devDependencies": { "chai": "^4.1.2", + "chai-as-promised": "^7.1.1", "eslint": "^4.19.1", "mocha": "^5.2.0", "nyc": "^12.0.2", - "sinon": "^6.0.0" + "sinon": "^6.0.0", + "sinon-chai": "^3.2.0" }, "nyc": { "exclude": [ diff --git a/commercial-paper/contract/test/contract.js b/commercial-paper/organization/digibank/contract/test/contract.js similarity index 100% rename from commercial-paper/contract/test/contract.js rename to commercial-paper/organization/digibank/contract/test/contract.js diff --git a/commercial-paper/organization/digibank/gateway/networkConnection.yaml b/commercial-paper/organization/digibank/gateway/networkConnection.yaml new file mode 100644 index 00000000..db50f318 --- /dev/null +++ b/commercial-paper/organization/digibank/gateway/networkConnection.yaml @@ -0,0 +1,129 @@ +--- +# +# The network connection profile provides client applications the information about the target +# blockchain network that are necessary for the applications to interact with it. These are all +# knowledge that must be acquired from out-of-band sources. This file provides such a source. +# +name: "basic-network" + +# +# Any properties with an "x-" prefix will be treated as application-specific, exactly like how naming +# in HTTP headers or swagger properties work. The SDK will simply ignore these fields and leave +# them for the applications to process. This is a mechanism for different components of an application +# to exchange information that are not part of the standard schema described below. In particular, +# the "x-type" property with the "hlfv1" value example below is used by Hyperledger Composer to +# determine the type of Fabric networks (v0.6 vs. v1.0) it needs to work with. +# +x-type: "hlfv1" + +# +# Describe what the target network is/does. +# +description: "The basic network" + +# +# Schema version of the content. Used by the SDK to apply the corresponding parsing rules. +# +version: "1.0" + +# +# [Optional]. But most apps would have this section so that channel objects can be constructed +# based on the content below. If an app is creating channels, then it likely will not need this +# section. +# +channels: + # name of the channel + mychannel: + # Required. list of orderers designated by the application to use for transactions on this + # channel. This list can be a result of access control ("org1" can only access "ordererA"), or + # operational decisions to share loads from applications among the orderers. The values must + # be "names" of orgs defined under "organizations/peers" + orderers: + - orderer.example.com + + # Required. list of peers from participating orgs + peers: + peer0.org1.example.com: + # [Optional]. will this peer be sent transaction proposals for endorsement? The peer must + # have the chaincode installed. The app can also use this property to decide which peers + # to send the chaincode install request. Default: true + endorsingPeer: true + + # [Optional]. will this peer be sent query proposals? The peer must have the chaincode + # installed. The app can also use this property to decide which peers to send the + # chaincode install request. Default: true + chaincodeQuery: true + + # [Optional]. will this peer be sent query proposals that do not require chaincodes, like + # queryBlock(), queryTransaction(), etc. Default: true + ledgerQuery: true + + # [Optional]. will this peer be the target of the SDK's listener registration? All peers can + # produce events but the app typically only needs to connect to one to listen to events. + # Default: true + eventSource: true + +# +# list of participating organizations in this network +# +organizations: + Org1: + mspid: Org1MSP + + peers: + - peer0.org1.example.com + + # [Optional]. Certificate Authorities issue certificates for identification purposes in a Fabric based + # network. Typically certificates provisioning is done in a separate process outside of the + # runtime network. Fabric-CA is a special certificate authority that provides a REST APIs for + # dynamic certificate management (enroll, revoke, re-enroll). The following section is only for + # Fabric-CA servers. + certificateAuthorities: + - ca-org1 + +# +# List of orderers to send transaction and channel create/update requests to. For the time +# being only one orderer is needed. If more than one is defined, which one get used by the +# SDK is implementation specific. Consult each SDK's documentation for its handling of orderers. +# +orderers: + orderer.example.com: + url: grpc://localhost:7050 + + # these are standard properties defined by the gRPC library + # they will be passed in as-is to gRPC client constructor + grpcOptions: + ssl-target-name-override: orderer.example.com + +# +# List of peers to send various requests to, including endorsement, query +# and event listener registration. +# +peers: + peer0.org1.example.com: + # this URL is used to send endorsement and query requests + url: grpc://localhost:7051 + + grpcOptions: + ssl-target-name-override: peer0.org1.example.com + request-timeout: 120001 + +# Fabric-CA is a special kind of Certificate Authority provided by Hyperledger Fabric which allows +# certificate management to be done via REST APIs. Application may choose to use a standard +# Certificate Authority instead of Fabric-CA, in which case this section would not be specified. +# +certificateAuthorities: + ca-org1: + url: http://localhost:7054 + # the properties specified under this object are passed to the 'http' client verbatim when + # making the request to the Fabric-CA server + httpOptions: + verify: false + + # Fabric-CA supports dynamic user enrollment via REST APIs. A "root" user, a.k.a registrar, is + # needed to enroll and invoke new users. + registrar: + - enrollId: admin + enrollSecret: adminpw + # [Optional] The optional name of the CA. + caName: ca-org1 diff --git a/commercial-paper/application/gateway/connectionProfile.yaml b/commercial-paper/organization/digibank/gateway/papernetConnection.yaml similarity index 86% rename from commercial-paper/application/gateway/connectionProfile.yaml rename to commercial-paper/organization/digibank/gateway/papernetConnection.yaml index 9c6115cc..7fc40283 100644 --- a/commercial-paper/application/gateway/connectionProfile.yaml +++ b/commercial-paper/organization/digibank/gateway/papernetConnection.yaml @@ -4,7 +4,7 @@ # blockchain network that are necessary for the applications to interact with it. These are all # knowledge that must be acquired from out-of-band sources. This file provides such a source. # -name: "global-trade-network" +name: "finance-networks" # # Any properties with an "x-" prefix will be treated as application-specific, exactly like how naming @@ -19,7 +19,7 @@ x-type: "hlfv1" # # Describe what the target network is/does. # -description: "The network to be in if you want to stay in the global trade business" +description: "A gateway connection file for the PaperNet networks" # # Schema version of the content. Used by the SDK to apply the corresponding parsing rules. @@ -59,13 +59,13 @@ version: "1.0" # channels: # name of the channel - PaperNet: + papernet: # Required. list of orderers designated by the application to use for transactions on this # channel. This list can be a result of access control ("org1" can only access "ordererA"), or # operational decisions to share loads from applications among the orderers. The values must # be "names" of orgs defined under "organizations/peers" orderers: - - orderer.example.com + - orderer.magnetocorp.com # Required. list of peers from participating orgs peers: @@ -119,7 +119,7 @@ organizations: # dynamic certificate management (enroll, revoke, re-enroll). The following section is only for # Fabric-CA servers. certificateAuthorities: - - ca-org1 + - ca-magnetocorp # [Optional]. If the application is going to make requests that are reserved to organization # administrators, including creating/updating channels, installing/instantiating chaincodes, it @@ -129,9 +129,9 @@ organizations: # this way. The SDK should allow applications to set the org admin identity via APIs, and only use # this route as an alternative when it exists. adminPrivateKey: - path: test/fixtures/channel/crypto-config/peerOrganizations/org1.example.com/users/Admin@org1.example.com/keystore/9022d671ceedbb24af3ea69b5a8136cc64203df6b9920e26f48123fcfcb1d2e9_sk + path: commercial-paper/organization/magnetocorp/users/Admin@magnetocorp/keystore/9022d671ceedbb24af3ea69b5a8136cc64203df6b9920e26f48123fcfcb1d2e9_sk signedCert: - path: test/fixtures/channel/crypto-config/peerOrganizations/org1.example.com/users/Admin@org1.example.com/signcerts/Admin@org1.example.com-cert.pem + path: comercial-paper/organization/magnetocorp/users/Admin@magnetocorp.com/signcerts/Admin@magnetocorp.com-cert.pem # the profile will contain public information about organizations other than the one it belongs to. # These are necessary information to make transaction lifecycles work, including MSP IDs and @@ -143,11 +143,11 @@ organizations: peers: - peer1.digibank.com certificateAuthorities: - - ca-org2 + - ca-digibank adminPrivateKey: - path: test/fixtures/channel/crypto-config/peerOrganizations/org2.example.com/users/Admin@org2.example.com/keystore/5a983ddcbefe52a7f9b8ee5b85a590c3e3a43c4ccd70c7795bec504e7f74848d_sk + path: commercial-paper/organization/digibank/users/Admin@digibank.com/keystore/5a983ddcbefe52a7f9b8ee5b85a590c3e3a43c4ccd70c7795bec504e7f74848d_sk signedCert: - path: test/fixtures/channel/crypto-config/peerOrganizations/org2.example.com/users/Admin@org2.example.com/signcerts/Admin@org2.example.com-cert.pem + path: commercial-paper/organization/digibank/users/Admin@digibank.com/signcerts/Admin@digibank.com-cert.pem # # List of orderers to send transaction and channel create/update requests to. For the time @@ -155,7 +155,7 @@ organizations: # SDK is implementation specific. Consult each SDK's documentation for its handling of orderers. # orderers: - orderer.example.com: + orderer.magnetocorp.com: url: grpcs://localhost:7050 # these are standard properties defined by the gRPC library @@ -164,7 +164,7 @@ orderers: ssl-target-name-override: orderer.example.com tlsCACerts: - path: test/fixtures/channel/crypto-config/ordererOrganizations/example.com/orderers/orderer.example.com/tlscacerts/example.com-cert.pem + path: comercial-paper/organization/magnetocorp/orderer/orderer.magnetocorp.com/tlscacerts/example.com-cert.pem # # List of peers to send various requests to, including endorsement, query @@ -202,7 +202,7 @@ certificateAuthorities: httpOptions: verify: false tlsCACerts: - path: test/fixtures/channel/crypto-config/peerOrganizations/org1.example.com/ca/org1.example.com-cert.pem + path: commercial-paper/organization/magnetocorp/ca/magnetocorp.com-cert.pem # Fabric-CA supports dynamic user enrollment via REST APIs. A "root" user, a.k.a registrar, is # needed to enroll and invoke new users. @@ -210,16 +210,16 @@ certificateAuthorities: - enrollId: admin enrollSecret: adminpw # [Optional] The optional name of the CA. - caName: ca-org1 + caName: ca-magnetocorp ca-org2: url: https://localhost:8054 httpOptions: verify: false tlsCACerts: - path: test/fixtures/channel/crypto-config/peerOrganizations/org2.example.com/ca/org2.example.com-cert.pem + path: commercial-paper/organization/digibank/ca/digibank.com-cert.pem registrar: - enrollId: admin enrollSecret: adminpw # [Optional] The optional name of the CA. - caName: ca-org2 \ No newline at end of file + caName: ca-digibank \ No newline at end of file diff --git a/commercial-paper/organization/magnetocorp/application/.eslintrc.js b/commercial-paper/organization/magnetocorp/application/.eslintrc.js new file mode 100644 index 00000000..22fbefc8 --- /dev/null +++ b/commercial-paper/organization/magnetocorp/application/.eslintrc.js @@ -0,0 +1,37 @@ +/* +SPDX-License-Identifier: Apache-2.0 +*/ + +module.exports = { + env: { + node: true, + mocha: true + }, + parserOptions: { + ecmaVersion: 8, + sourceType: 'script' + }, + extends: "eslint:recommended", + rules: { + indent: ['error', 4], + 'linebreak-style': ['error', 'unix'], + quotes: ['error', 'single'], + semi: ['error', 'always'], + 'no-unused-vars': ['error', { args: 'none' }], + 'no-console': 'off', + curly: 'error', + eqeqeq: 'error', + 'no-throw-literal': 'error', + strict: 'error', + 'no-var': 'error', + 'dot-notation': 'error', + 'no-tabs': 'error', + 'no-trailing-spaces': 'error', + 'no-use-before-define': 'error', + 'no-useless-call': 'error', + 'no-with': 'error', + 'operator-linebreak': 'error', + yoda: 'error', + 'quote-props': ['error', 'as-needed'] + } +}; \ No newline at end of file diff --git a/commercial-paper/organization/magnetocorp/application/addToWallet.js b/commercial-paper/organization/magnetocorp/application/addToWallet.js new file mode 100644 index 00000000..f0403533 --- /dev/null +++ b/commercial-paper/organization/magnetocorp/application/addToWallet.js @@ -0,0 +1,45 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + */ + +'use strict'; + +// Bring key classes into scope, most importantly Fabric SDK network class +const fs = require('fs'); +const { FileSystemWallet, X509WalletMixin } = require('fabric-network'); +const path = require('path'); + +const fixtures = path.resolve(__dirname, '../../../../basic-network'); + +// A wallet stores a collection of identities +const wallet = new FileSystemWallet('../identity/user/isabella/wallet'); + +async function main() { + + // Main try/catch block + try { + + // Identity to credentials to be stored in the wallet + const credPath = path.join(fixtures, '/crypto-config/peerOrganizations/org1.example.com/users/User1@org1.example.com'); + const cert = fs.readFileSync(path.join(credPath, '/msp/signcerts/User1@org1.example.com-cert.pem')).toString(); + const key = fs.readFileSync(path.join(credPath, '/msp/keystore/c75bd6911aca808941c3557ee7c97e90f3952e379497dc55eb903f31b50abc83_sk')).toString(); + + // Load credentials into wallet + const identityLabel = 'User1@org1.example.com'; + const identity = X509WalletMixin.createIdentity('Org1MSP', cert, key); + + await wallet.import(identityLabel, identity); + + } catch (error) { + console.log(`Error adding to wallet. ${error}`); + console.log(error.stack); + } +} + +main().then(() => { + console.log('done'); +}).catch((e) => { + console.log(e); + console.log(e.stack); + process.exit(-1); +}); \ No newline at end of file diff --git a/commercial-paper/organization/magnetocorp/application/issue.js b/commercial-paper/organization/magnetocorp/application/issue.js new file mode 100644 index 00000000..3e50c7bf --- /dev/null +++ b/commercial-paper/organization/magnetocorp/application/issue.js @@ -0,0 +1,102 @@ +/* +SPDX-License-Identifier: Apache-2.0 +*/ + +/* + * This application has 6 basic steps: + * 1. Select an identity from a wallet + * 2. Connect to network gateway + * 3. Access PaperNet network + * 4. Construct request to issue commercial paper + * 5. Submit transaction + * 6. Process response + */ + +'use strict'; + +// Bring key classes into scope, most importantly Fabric SDK network class +const fs = require('fs'); +const yaml = require('js-yaml'); +const { FileSystemWallet, Gateway } = require('fabric-network'); +const CommercialPaper = require('../contract/lib/paper.js'); + +// A wallet stores a collection of identities for use +//const wallet = new FileSystemWallet('../user/isabella/wallet'); +const wallet = new FileSystemWallet('../identity/user/isabella/wallet'); + +// Main program function +async function main() { + + // A gateway defines the peers used to access Fabric networks + const gateway = new Gateway(); + + // Main try/catch block + try { + + // Specify userName for network access + // const userName = 'isabella.issuer@magnetocorp.com'; + const userName = 'User1@org1.example.com'; + + // Load connection profile; will be used to locate a gateway + let connectionProfile = yaml.safeLoad(fs.readFileSync('../gateway/networkConnection.yaml', 'utf8')); + + // Set connection options; identity and wallet + let connectionOptions = { + identity: userName, + wallet: wallet, + discovery: { enabled:false, asLocalhost: true } + }; + + // Connect to gateway using application specified parameters + console.log('Connect to Fabric gateway.'); + + await gateway.connect(connectionProfile, connectionOptions); + + // Access PaperNet network + console.log('Use network channel: mychannel.'); + + const network = await gateway.getNetwork('mychannel'); + + // Get addressability to commercial paper contract + console.log('Use org.papernet.commercialpaper smart contract.'); + + const contract = await network.getContract('papercontract', 'org.papernet.commercialpaper'); + + // issue commercial paper + console.log('Submit commercial paper issue transaction.'); + + const issueResponse = await contract.submitTransaction('issue', 'MagnetoCorp', '00001', '2020-05-31', '2020-11-30', '5000000'); + + // process response + console.log('Process issue transaction response.'); + + let paper = CommercialPaper.fromBuffer(issueResponse); + + console.log(`${paper.issuer} commercial paper : ${paper.paperNumber} successfully issued for value ${paper.faceValue}`); + console.log('Transaction complete.'); + + } catch (error) { + + console.log(`Error processing transaction. ${error}`); + console.log(error.stack); + + } finally { + + // Disconnect from the gateway + console.log('Disconnect from Fabric gateway.') + gateway.disconnect(); + + } +} +main().then(() => { + + console.log('Issue program complete.'); + +}).catch((e) => { + + console.log('Issue program exception.'); + console.log(e); + console.log(e.stack); + process.exit(-1); + +}); \ No newline at end of file diff --git a/commercial-paper/organization/magnetocorp/application/package.json b/commercial-paper/organization/magnetocorp/application/package.json new file mode 100644 index 00000000..2ed92f26 --- /dev/null +++ b/commercial-paper/organization/magnetocorp/application/package.json @@ -0,0 +1,20 @@ +{ + "name": "nodejs", + "version": "1.0.0", + "description": "", + "main": "issue.js", + "scripts": { + "test": "rm -rf _idwallet && node addToWallet.js && node issue.js" + }, + "keywords": [], + "author": "", + "license": "ISC", + "dependencies": { + "fabric-network": "^1.4.0-beta", + "fabric-client": "^1.4.0-beta", + "js-yaml": "^3.12.0" + }, + "devDependencies": { + "eslint": "^5.6.0" + } +} diff --git a/commercial-paper/organization/magnetocorp/configuration/cli/docker-compose.yml b/commercial-paper/organization/magnetocorp/configuration/cli/docker-compose.yml new file mode 100644 index 00000000..8f887d3e --- /dev/null +++ b/commercial-paper/organization/magnetocorp/configuration/cli/docker-compose.yml @@ -0,0 +1,38 @@ +# +# Copyright IBM Corp All Rights Reserved +# +# SPDX-License-Identifier: Apache-2.0 +# +version: '2' + +networks: + basic: + external: + name: net_basic + +services: + cliMagnetoCorp: + container_name: cliMagnetoCorp + image: hyperledger/fabric-tools + tty: true + environment: + - GOPATH=/opt/gopath + - CORE_VM_ENDPOINT=unix:///host/var/run/docker.sock + - CORE_LOGGING_LEVEL=info + - CORE_PEER_ID=cli + - CORE_PEER_ADDRESS=peer0.org1.example.com:7051 + - CORE_PEER_LOCALMSPID=Org1MSP + - CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp + - CORE_CHAINCODE_KEEPALIVE=10 + working_dir: /opt/gopath/src/github.com/hyperledger/fabric/peer + command: /bin/bash + volumes: + - /var/run/:/host/var/run/ + - ./../../../../organization/magnetocorp:/opt/gopath/src/github.com/ + - ./../../../../../basic-network/crypto-config:/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ + networks: + - basic + #depends_on: + # - orderer.example.com + # - peer0.org1.example.com + # - couchdb diff --git a/commercial-paper/organization/magnetocorp/configuration/cli/monitordocker.sh b/commercial-paper/organization/magnetocorp/configuration/cli/monitordocker.sh new file mode 100755 index 00000000..355acf07 --- /dev/null +++ b/commercial-paper/organization/magnetocorp/configuration/cli/monitordocker.sh @@ -0,0 +1,25 @@ +#!/bin/bash + +# This script uses the logspout and http stream tools to let you watch the docker containers +# in action. +# +# More information at https://github.com/gliderlabs/logspout/tree/master/httpstream + +if [ -z "$1" ]; then + DOCKER_NETWORK=basicnetwork_basic +else + DOCKER_NETWORK="$1" +fi + +echo Starting monitoring on all containers on the network ${DOCKER_NETWORK} + +docker kill logspout 2> /dev/null 1>&2 || true +docker rm logspout 2> /dev/null 1>&2 || true + +docker run -d --name="logspout" \ + --volume=/var/run/docker.sock:/var/run/docker.sock \ + --publish=127.0.0.1:8000:80 \ + --network ${DOCKER_NETWORK} \ + gliderlabs/logspout +sleep 3 +curl http://127.0.0.1:8000/logs \ No newline at end of file diff --git a/commercial-paper/organization/magnetocorp/contract/.editorconfig b/commercial-paper/organization/magnetocorp/contract/.editorconfig new file mode 100755 index 00000000..75a13be2 --- /dev/null +++ b/commercial-paper/organization/magnetocorp/contract/.editorconfig @@ -0,0 +1,16 @@ +# +# SPDX-License-Identifier: Apache-2.0 +# + +root = true + +[*] +indent_style = space +indent_size = 4 +end_of_line = lf +charset = utf-8 +trim_trailing_whitespace = true +insert_final_newline = true + +[*.md] +trim_trailing_whitespace = false diff --git a/commercial-paper/organization/magnetocorp/contract/.eslintignore b/commercial-paper/organization/magnetocorp/contract/.eslintignore new file mode 100644 index 00000000..15958470 --- /dev/null +++ b/commercial-paper/organization/magnetocorp/contract/.eslintignore @@ -0,0 +1,5 @@ +# +# SPDX-License-Identifier: Apache-2.0 +# + +coverage diff --git a/commercial-paper/organization/magnetocorp/contract/.eslintrc.js b/commercial-paper/organization/magnetocorp/contract/.eslintrc.js new file mode 100644 index 00000000..6772c660 --- /dev/null +++ b/commercial-paper/organization/magnetocorp/contract/.eslintrc.js @@ -0,0 +1,37 @@ +/* +SPDX-License-Identifier: Apache-2.0 +*/ + +module.exports = { + env: { + node: true, + mocha: true + }, + parserOptions: { + ecmaVersion: 8, + sourceType: 'script' + }, + extends: "eslint:recommended", + rules: { + indent: ['error', 4], + 'linebreak-style': ['error', 'unix'], + quotes: ['error', 'single'], + semi: ['error', 'always'], + 'no-unused-vars': ['error', { args: 'none' }], + 'no-console': 'off', + curly: 'error', + eqeqeq: 'error', + 'no-throw-literal': 'error', + strict: 'error', + 'no-var': 'error', + 'dot-notation': 'error', + 'no-tabs': 'error', + 'no-trailing-spaces': 'error', + 'no-use-before-define': 'error', + 'no-useless-call': 'error', + 'no-with': 'error', + 'operator-linebreak': 'error', + yoda: 'error', + 'quote-props': ['error', 'as-needed'] + } +}; diff --git a/commercial-paper/organization/magnetocorp/contract/.npmignore b/commercial-paper/organization/magnetocorp/contract/.npmignore new file mode 100644 index 00000000..a00ca941 --- /dev/null +++ b/commercial-paper/organization/magnetocorp/contract/.npmignore @@ -0,0 +1,77 @@ +# +# SPDX-License-Identifier: Apache-2.0 +# + +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* + +# Runtime data +pids +*.pid +*.seed +*.pid.lock + +# Directory for instrumented libs generated by jscoverage/JSCover +lib-cov + +# Coverage directory used by tools like istanbul +coverage + +# nyc test coverage +.nyc_output + +# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) +.grunt + +# Bower dependency directory (https://bower.io/) +bower_components + +# node-waf configuration +.lock-wscript + +# Compiled binary addons (https://nodejs.org/api/addons.html) +build/Release + +# Dependency directories +node_modules/ +jspm_packages/ + +# TypeScript v1 declaration files +typings/ + +# Optional npm cache directory +.npm + +# Optional eslint cache +.eslintcache + +# Optional REPL history +.node_repl_history + +# Output of 'npm pack' +*.tgz + +# Yarn Integrity file +.yarn-integrity + +# dotenv environment variables file +.env + +# parcel-bundler cache (https://parceljs.org/) +.cache + +# next.js build output +.next + +# nuxt.js build output +.nuxt + +# vuepress build output +.vuepress/dist + +# Serverless directories +.serverless diff --git a/commercial-paper/organization/magnetocorp/contract/index.js b/commercial-paper/organization/magnetocorp/contract/index.js new file mode 100644 index 00000000..b957b5e3 --- /dev/null +++ b/commercial-paper/organization/magnetocorp/contract/index.js @@ -0,0 +1,8 @@ +/* +SPDX-License-Identifier: Apache-2.0 +*/ + +'use strict'; + +const cpcontract = require('./lib/papercontract.js'); +module.exports.contracts = [cpcontract]; \ No newline at end of file diff --git a/commercial-paper/organization/magnetocorp/contract/ledger-api/state.js b/commercial-paper/organization/magnetocorp/contract/ledger-api/state.js new file mode 100644 index 00000000..df2fbe57 --- /dev/null +++ b/commercial-paper/organization/magnetocorp/contract/ledger-api/state.js @@ -0,0 +1,98 @@ +/* +SPDX-License-Identifier: Apache-2.0 +*/ + +'use strict'; + +/** + * State class. States have a class, unique key, and a lifecycle current state + * the current state is determined by the specific subclass + */ +class State { + + /** + * @param {String|Object} class An indentifiable class of the instance + * @param {keyParts[]} elements to pull together to make a key for the objects + */ + constructor(stateClass, keyParts) { + this.class = stateClass; + this.key = State.makeKey(keyParts); + this.currentState = null; + } + + getClass() { + return this.class; + } + + getKey() { + return this.key; + } + + getSplitKey(){ + return State.splitKey(this.key); + } + + getCurrentState(){ + return this.currentState; + } + + serialize() { + return State.serialize(this); + } + + /** + * Convert object to buffer containing JSON data serialization + * Typically used before putState()ledger API + * @param {Object} JSON object to serialize + * @return {buffer} buffer with the data to store + */ + static serialize(object) { + return Buffer.from(JSON.stringify(object)); + } + + /** + * Deserialize object into one of a set of supported JSON classes + * i.e. Covert serialized data to JSON object + * Typically used after getState() ledger API + * @param {data} data to deserialize into JSON object + * @param (supportedClasses) the set of classes data can be serialized to + * @return {json} json with the data to store + */ + static deserialize(data, supportedClasses) { + let json = JSON.parse(data.toString()); + let objClass = supportedClasses[json.class]; + if (!objClass) { + throw new Error(`Unknown class of ${json.class}`); + } + let object = new (objClass)(json); + + return object; + } + + /** + * Deserialize object into specific object class + * Typically used after getState() ledger API + * @param {data} data to deserialize into JSON object + * @return {json} json with the data to store + */ + static deserializeClass(data, objClass) { + let json = JSON.parse(data.toString()); + let object = new (objClass)(json); + return object; + } + + /** + * Join the keyParts to make a unififed string + * @param (String[]) keyParts + */ + static makeKey(keyParts) { + return keyParts.map(part => JSON.stringify(part)).join(':'); + } + + static splitKey(key){ + return key.split(':'); + } + +} + +module.exports = State; \ No newline at end of file diff --git a/commercial-paper/organization/magnetocorp/contract/ledger-api/statelist.js b/commercial-paper/organization/magnetocorp/contract/ledger-api/statelist.js new file mode 100644 index 00000000..3c39671a --- /dev/null +++ b/commercial-paper/organization/magnetocorp/contract/ledger-api/statelist.js @@ -0,0 +1,68 @@ +/* +SPDX-License-Identifier: Apache-2.0 +*/ + +'use strict'; +const State = require('./state.js'); + +/** + * StateList provides a named virtual container for a set of ledger states. + * Each state has a unique key which associates it with the container, rather + * than the container containing a link to the state. This minimizes collisions + * for parallel transactions on different states. + */ +class StateList { + + /** + * Store Fabric context for subsequent API access, and name of list + */ + constructor(ctx, listName) { + this.ctx = ctx; + this.name = listName; + this.supportedClasses = {}; + + } + + /** + * Add a state to the list. Creates a new state in worldstate with + * appropriate composite key. Note that state defines its own key. + * State object is serialized before writing. + */ + async addState(state) { + let key = this.ctx.stub.createCompositeKey(this.name, state.getSplitKey()); + let data = State.serialize(state); + await this.ctx.stub.putState(key, data); + } + + /** + * Get a state from the list using supplied keys. Form composite + * keys to retrieve state from world state. State data is deserialized + * into JSON object before being returned. + */ + async getState(key) { + let ledgerKey = this.ctx.stub.createCompositeKey(this.name, State.splitKey(key)); + let data = await this.ctx.stub.getState(ledgerKey); + let state = State.deserialize(data, this.supportedClasses); + return state; + } + + /** + * Update a state in the list. Puts the new state in world state with + * appropriate composite key. Note that state defines its own key. + * A state is serialized before writing. Logic is very similar to + * addState() but kept separate becuase it is semantically distinct. + */ + async updateState(state) { + let key = this.ctx.stub.createCompositeKey(this.name, state.getSplitKey()); + let data = State.serialize(state); + await this.ctx.stub.putState(key, data); + } + + /** Stores the class for future deserialization */ + use(stateClass) { + this.supportedClasses[stateClass.getClass()] = stateClass; + } + +} + +module.exports = StateList; \ No newline at end of file diff --git a/commercial-paper/organization/magnetocorp/contract/lib/paper.js b/commercial-paper/organization/magnetocorp/contract/lib/paper.js new file mode 100644 index 00000000..9d76adac --- /dev/null +++ b/commercial-paper/organization/magnetocorp/contract/lib/paper.js @@ -0,0 +1,102 @@ +/* +SPDX-License-Identifier: Apache-2.0 +*/ + +'use strict'; + +// Utility class for ledger state +const State = require('./../ledger-api/state.js'); + +// Enumerate commercial paper state values +const cpState = { + ISSUED: 1, + TRADING: 2, + REDEEMED: 3 +}; + +/** + * CommercialPaper class extends State class + * Class will be used by application and smart contract to define a paper + */ +class CommercialPaper extends State { + + constructor(obj) { + super(CommercialPaper.getClass(), [obj.issuer, obj.paperNumber]); + Object.assign(this, obj); + } + + /** + * Basic getters and setters + */ + getIssuer() { + return this.issuer; + } + + setIssuer(newIssuer) { + this.issuer = newIssuer; + } + + getOwner() { + return this.owner; + } + + setOwner(newOwner) { + this.owner = newOwner; + } + + /** + * Useful methods to encapsulate commercial paper states + */ + setIssued() { + this.currentState = cpState.ISSUED; + } + + setTrading() { + this.currentState = cpState.TRADING; + } + + setRedeemed() { + this.currentState = cpState.REDEEMED; + } + + isIssued() { + return this.currentState === cpState.ISSUED; + } + + isTrading() { + return this.currentState === cpState.TRADING; + } + + isRedeemed() { + return this.currentState === cpState.REDEEMED; + } + + static fromBuffer(buffer) { + return CommercialPaper.deserialize(Buffer.from(JSON.parse(buffer))); + } + + toBuffer() { + return Buffer.from(JSON.stringify(this)); + } + + /** + * Deserialize a state data to commercial paper + * @param {Buffer} data to form back into the object + */ + static deserialize(data) { + return State.deserializeClass(data, CommercialPaper); + } + + /** + * Factory method to create a commercial paper object + */ + static createInstance(issuer, paperNumber, issueDateTime, maturityDateTime, faceValue) { + return new CommercialPaper({ issuer, paperNumber, issueDateTime, maturityDateTime, faceValue }); + } + + static getClass() { + return 'org.papernet.commercialpaper'; + } +} + +module.exports = CommercialPaper; diff --git a/commercial-paper/organization/magnetocorp/contract/lib/papercontract.js b/commercial-paper/organization/magnetocorp/contract/lib/papercontract.js new file mode 100644 index 00000000..c9e54aa3 --- /dev/null +++ b/commercial-paper/organization/magnetocorp/contract/lib/papercontract.js @@ -0,0 +1,156 @@ +/* +SPDX-License-Identifier: Apache-2.0 +*/ + +'use strict'; + +// Fabric smart contract classes +const { Contract, Context } = require('fabric-contract-api'); + +// PaperNet specifc classes +const CommercialPaper = require('./paper.js'); +const PaperList = require('./paperlist.js'); + +/** + * A custom context provides easy access to list of all commercial papers + */ +class CommercialPaperContext extends Context { + + constructor() { + super(); + // All papers are held in a list of papers + this.paperList = new PaperList(this); + } + +} + +/** + * Define commercial paper smart contract by extending Fabric Contract class + * + */ +class CommercialPaperContract extends Contract { + + constructor() { + // Unique namespace when multiple contracts per chaincode file + super('org.papernet.commercialpaper'); + } + + /** + * Define a custom context for commercial paper + */ + createContext() { + return new CommercialPaperContext(); + } + + /** + * Instantiate to perform any setup of the ledger that might be required. + * @param {Context} ctx the transaction context + */ + async instantiate(ctx) { + // No implementation required with this example + // It could be where data migration is performed, if necessary + console.log('Instantiate the contract'); + } + + /** + * Issue commercial paper + * + * @param {Context} ctx the transaction context + * @param {String} issuer commercial paper issuer + * @param {Integer} paperNumber paper number for this issuer + * @param {String} issueDateTime paper issue date + * @param {String} maturityDateTime paper maturity date + * @param {Integer} faceValue face value of paper + */ + async issue(ctx, issuer, paperNumber, issueDateTime, maturityDateTime, faceValue) { + + // create an instance of the paper + let paper = CommercialPaper.createInstance(issuer, paperNumber, issueDateTime, maturityDateTime, faceValue); + + // Smart contract, rather than paper, moves paper into ISSUED state + paper.setIssued(); + + // Newly issued paper is owned by the issuer + paper.setOwner(issuer); + + // Add the paper to the list of all similar commercial papers in the ledger world state + await ctx.paperList.addPaper(paper); + + // Must return a serialized paper to caller of smart contract + return paper.toBuffer(); + } + + /** + * Buy commercial paper + * + * @param {Context} ctx the transaction context + * @param {String} issuer commercial paper issuer + * @param {Integer} paperNumber paper number for this issuer + * @param {String} currentOwner current owner of paper + * @param {String} newOwner new owner of paper + * @param {Integer} price price paid for this paper + * @param {String} purchaseDateTime time paper was purchased (i.e. traded) + */ + async buy(ctx, issuer, paperNumber, currentOwner, newOwner, price, purchaseDateTime) { + + // Retrieve the current paper using key fields provided + let paperKey = CommercialPaper.makeKey([issuer, paperNumber]); + let paper = await ctx.paperList.getPaper(paperKey); + + // Validate current owner + if (paper.getOwner() !== currentOwner) { + throw new Error('Paper ' + issuer + paperNumber + ' is not owned by ' + currentOwner); + } + + // First buy moves state from ISSUED to TRADING + if (paper.isIssued()) { + paper.setTrading(); + } + + // Check paper is not already REDEEMED + if (paper.isTrading()) { + paper.setOwner(newOwner); + } else { + throw new Error('Paper ' + issuer + paperNumber + ' is not trading. Current state = ' +paper.getCurrentState()); + } + + // Update the paper + await ctx.paperList.updatePaper(paper); + return paper.toBuffer(); + } + + /** + * Redeem commercial paper + * + * @param {Context} ctx the transaction context + * @param {String} issuer commercial paper issuer + * @param {Integer} paperNumber paper number for this issuer + * @param {String} redeemingOwner redeeming owner of paper + * @param {String} redeemDateTime time paper was redeemed + */ + async redeem(ctx, issuer, paperNumber, redeemingOwner, redeemDateTime) { + + let paperKey = CommercialPaper.makeKey([issuer, paperNumber]); + + let paper = await ctx.paperList.getPaper(paperKey); + + // Check paper is not REDEEMED + if (paper.isRedeemed()) { + throw new Error('Paper ' + issuer + paperNumber + ' already redeemed'); + } + + // Verify that the redeemer owns the commercial paper before redeeming it + if (paper.getOwner() === redeemingOwner) { + paper.setOwner(paper.getIssuer()); + paper.setRedeemed(); + } else { + throw new Error('Redeeming owner does not own paper' + issuer + paperNumber); + } + + await ctx.paperList.updatePaper(paper); + return paper.toBuffer(); + } + +} + +module.exports = CommercialPaperContract; diff --git a/commercial-paper/organization/magnetocorp/contract/lib/paperlist.js b/commercial-paper/organization/magnetocorp/contract/lib/paperlist.js new file mode 100644 index 00000000..ac5d7183 --- /dev/null +++ b/commercial-paper/organization/magnetocorp/contract/lib/paperlist.js @@ -0,0 +1,33 @@ +/* +SPDX-License-Identifier: Apache-2.0 +*/ + +'use strict'; + +// Utility class for collections of ledger states -- a state list +const StateList = require('./../ledger-api/statelist.js'); + +const CommercialPaper = require('./paper.js'); + +class PaperList extends StateList { + + constructor(ctx) { + super(ctx, 'org.papernet.commercialpaperlist'); + this.use(CommercialPaper); + } + + async addPaper(paper) { + return this.addState(paper); + } + + async getPaper(paperKey) { + return this.getState(paperKey); + } + + async updatePaper(paper) { + return this.updateState(paper); + } +} + + +module.exports = PaperList; \ No newline at end of file diff --git a/commercial-paper/organization/magnetocorp/contract/package.json b/commercial-paper/organization/magnetocorp/contract/package.json new file mode 100644 index 00000000..6d79d096 --- /dev/null +++ b/commercial-paper/organization/magnetocorp/contract/package.json @@ -0,0 +1,49 @@ +{ + "name": "papernet-js", + "version": "0.0.1", + "description": "Papernet Contract", + "main": "index.js", + "engines": { + "node": ">=8", + "npm": ">=5" + }, + "scripts": { + "lint": "eslint .", + "pretest": "npm run lint", + "test": "nyc mocha test --recursive", + "start": "fabric-chaincode-node start", + "mocha": "mocha test --recursive" + }, + "engineStrict": true, + "author": "hyperledger", + "license": "Apache-2.0", + "dependencies": { + "fabric-contract-api": "^1.4.0-snapshot.17", + "fabric-shim": "^1.4.0-snapshot.27" + }, + "devDependencies": { + "chai": "^4.1.2", + "chai-as-promised": "^7.1.1", + "eslint": "^4.19.1", + "mocha": "^5.2.0", + "nyc": "^12.0.2", + "sinon": "^6.0.0", + "sinon-chai": "^3.2.0" + }, + "nyc": { + "exclude": [ + "coverage/**", + "test/**" + ], + "reporter": [ + "text-summary", + "html" + ], + "all": true, + "check-coverage": true, + "statements": 100, + "branches": 100, + "functions": 100, + "lines": 100 + } +} diff --git a/commercial-paper/organization/magnetocorp/contract/test/contract.js b/commercial-paper/organization/magnetocorp/contract/test/contract.js new file mode 100644 index 00000000..e0aafd5e --- /dev/null +++ b/commercial-paper/organization/magnetocorp/contract/test/contract.js @@ -0,0 +1,41 @@ +/* +SPDX-License-Identifier: Apache-2.0 +*/ +'use strict'; + +const Chaincode = require('../lib/chaincode'); +const { Stub } = require('fabric-shim'); + +require('chai').should(); +const sinon = require('sinon'); + +describe('Chaincode', () => { + + describe('#Init', () => { + + it('should work', async () => { + const cc = new Chaincode(); + const stub = sinon.createStubInstance(Stub); + stub.getFunctionAndParameters.returns({ fcn: 'initFunc', params: [] }); + const res = await cc.Init(stub); + res.status.should.equal(Stub.RESPONSE_CODE.OK); + }); + + }); + + describe('#Invoke', async () => { + + it('should work', async () => { + const cc = new Chaincode(); + const stub = sinon.createStubInstance(Stub); + stub.getFunctionAndParameters.returns({ fcn: 'initFunc', params: [] }); + let res = await cc.Init(stub); + res.status.should.equal(Stub.RESPONSE_CODE.OK); + stub.getFunctionAndParameters.returns({ fcn: 'invokeFunc', params: [] }); + res = await cc.Invoke(stub); + res.status.should.equal(Stub.RESPONSE_CODE.OK); + }); + + }); + +}); diff --git a/commercial-paper/organization/magnetocorp/gateway/networkConnection.yaml b/commercial-paper/organization/magnetocorp/gateway/networkConnection.yaml new file mode 100644 index 00000000..db50f318 --- /dev/null +++ b/commercial-paper/organization/magnetocorp/gateway/networkConnection.yaml @@ -0,0 +1,129 @@ +--- +# +# The network connection profile provides client applications the information about the target +# blockchain network that are necessary for the applications to interact with it. These are all +# knowledge that must be acquired from out-of-band sources. This file provides such a source. +# +name: "basic-network" + +# +# Any properties with an "x-" prefix will be treated as application-specific, exactly like how naming +# in HTTP headers or swagger properties work. The SDK will simply ignore these fields and leave +# them for the applications to process. This is a mechanism for different components of an application +# to exchange information that are not part of the standard schema described below. In particular, +# the "x-type" property with the "hlfv1" value example below is used by Hyperledger Composer to +# determine the type of Fabric networks (v0.6 vs. v1.0) it needs to work with. +# +x-type: "hlfv1" + +# +# Describe what the target network is/does. +# +description: "The basic network" + +# +# Schema version of the content. Used by the SDK to apply the corresponding parsing rules. +# +version: "1.0" + +# +# [Optional]. But most apps would have this section so that channel objects can be constructed +# based on the content below. If an app is creating channels, then it likely will not need this +# section. +# +channels: + # name of the channel + mychannel: + # Required. list of orderers designated by the application to use for transactions on this + # channel. This list can be a result of access control ("org1" can only access "ordererA"), or + # operational decisions to share loads from applications among the orderers. The values must + # be "names" of orgs defined under "organizations/peers" + orderers: + - orderer.example.com + + # Required. list of peers from participating orgs + peers: + peer0.org1.example.com: + # [Optional]. will this peer be sent transaction proposals for endorsement? The peer must + # have the chaincode installed. The app can also use this property to decide which peers + # to send the chaincode install request. Default: true + endorsingPeer: true + + # [Optional]. will this peer be sent query proposals? The peer must have the chaincode + # installed. The app can also use this property to decide which peers to send the + # chaincode install request. Default: true + chaincodeQuery: true + + # [Optional]. will this peer be sent query proposals that do not require chaincodes, like + # queryBlock(), queryTransaction(), etc. Default: true + ledgerQuery: true + + # [Optional]. will this peer be the target of the SDK's listener registration? All peers can + # produce events but the app typically only needs to connect to one to listen to events. + # Default: true + eventSource: true + +# +# list of participating organizations in this network +# +organizations: + Org1: + mspid: Org1MSP + + peers: + - peer0.org1.example.com + + # [Optional]. Certificate Authorities issue certificates for identification purposes in a Fabric based + # network. Typically certificates provisioning is done in a separate process outside of the + # runtime network. Fabric-CA is a special certificate authority that provides a REST APIs for + # dynamic certificate management (enroll, revoke, re-enroll). The following section is only for + # Fabric-CA servers. + certificateAuthorities: + - ca-org1 + +# +# List of orderers to send transaction and channel create/update requests to. For the time +# being only one orderer is needed. If more than one is defined, which one get used by the +# SDK is implementation specific. Consult each SDK's documentation for its handling of orderers. +# +orderers: + orderer.example.com: + url: grpc://localhost:7050 + + # these are standard properties defined by the gRPC library + # they will be passed in as-is to gRPC client constructor + grpcOptions: + ssl-target-name-override: orderer.example.com + +# +# List of peers to send various requests to, including endorsement, query +# and event listener registration. +# +peers: + peer0.org1.example.com: + # this URL is used to send endorsement and query requests + url: grpc://localhost:7051 + + grpcOptions: + ssl-target-name-override: peer0.org1.example.com + request-timeout: 120001 + +# Fabric-CA is a special kind of Certificate Authority provided by Hyperledger Fabric which allows +# certificate management to be done via REST APIs. Application may choose to use a standard +# Certificate Authority instead of Fabric-CA, in which case this section would not be specified. +# +certificateAuthorities: + ca-org1: + url: http://localhost:7054 + # the properties specified under this object are passed to the 'http' client verbatim when + # making the request to the Fabric-CA server + httpOptions: + verify: false + + # Fabric-CA supports dynamic user enrollment via REST APIs. A "root" user, a.k.a registrar, is + # needed to enroll and invoke new users. + registrar: + - enrollId: admin + enrollSecret: adminpw + # [Optional] The optional name of the CA. + caName: ca-org1 diff --git a/commercial-paper/organization/magnetocorp/gateway/papernetConnection.yaml b/commercial-paper/organization/magnetocorp/gateway/papernetConnection.yaml new file mode 100644 index 00000000..7fc40283 --- /dev/null +++ b/commercial-paper/organization/magnetocorp/gateway/papernetConnection.yaml @@ -0,0 +1,225 @@ +--- +# +# The network connection profile provides client applications the information about the target +# blockchain network that are necessary for the applications to interact with it. These are all +# knowledge that must be acquired from out-of-band sources. This file provides such a source. +# +name: "finance-networks" + +# +# Any properties with an "x-" prefix will be treated as application-specific, exactly like how naming +# in HTTP headers or swagger properties work. The SDK will simply ignore these fields and leave +# them for the applications to process. This is a mechanism for different components of an application +# to exchange information that are not part of the standard schema described below. In particular, +# the "x-type" property with the "hlfv1" value example below is used by Hyperledger Composer to +# determine the type of Fabric networks (v0.6 vs. v1.0) it needs to work with. +# +x-type: "hlfv1" + +# +# Describe what the target network is/does. +# +description: "A gateway connection file for the PaperNet networks" + +# +# Schema version of the content. Used by the SDK to apply the corresponding parsing rules. +# +version: "1.0" + +# +# The client section is SDK-specific. The sample below is for the node.js SDK +# +#client: + # Which organization does this application instance belong to? The value must be the name of an org + # defined under "organizations" + #organization: Org1 + + # Some SDKs support pluggable KV stores, the properties under "credentialStore" + # are implementation specific + #credentialStore: + # [Optional]. Specific to FileKeyValueStore.js or similar implementations in other SDKs. Can be others + # if using an alternative impl. For instance, CouchDBKeyValueStore.js would require an object + # here for properties like url, db name, etc. + #path: "/tmp/hfc-kvs" + + # [Optional]. Specific to the CryptoSuite implementation. Software-based implementations like + # CryptoSuite_ECDSA_AES.js in node SDK requires a key store. PKCS#11 based implementations does + # not. + #cryptoStore: + # Specific to the underlying KeyValueStore that backs the crypto key store. + #path: "/tmp/hfc-cvs" + + # [Optional]. Specific to Composer environment + #wallet: wallet-name + +# +# [Optional]. But most apps would have this section so that channel objects can be constructed +# based on the content below. If an app is creating channels, then it likely will not need this +# section. +# +channels: + # name of the channel + papernet: + # Required. list of orderers designated by the application to use for transactions on this + # channel. This list can be a result of access control ("org1" can only access "ordererA"), or + # operational decisions to share loads from applications among the orderers. The values must + # be "names" of orgs defined under "organizations/peers" + orderers: + - orderer.magnetocorp.com + + # Required. list of peers from participating orgs + peers: + peer1.magnetocorp.com: + # [Optional]. will this peer be sent transaction proposals for endorsement? The peer must + # have the chaincode installed. The app can also use this property to decide which peers + # to send the chaincode install request. Default: true + endorsingPeer: true + + # [Optional]. will this peer be sent query proposals? The peer must have the chaincode + # installed. The app can also use this property to decide which peers to send the + # chaincode install request. Default: true + chaincodeQuery: true + + # [Optional]. will this peer be sent query proposals that do not require chaincodes, like + # queryBlock(), queryTransaction(), etc. Default: true + ledgerQuery: true + + # [Optional]. will this peer be the target of the SDK's listener registration? All peers can + # produce events but the app typically only needs to connect to one to listen to events. + # Default: true + eventSource: true + + peer2.digibank.com: + endorsingPeer: true + chaincodeQuery: false + ledgerQuery: true + eventSource: true + + # [Optional]. what chaincodes are expected to exist on this channel? The application can use + # this information to validate that the target peers are in the expected state by comparing + # this list with the query results of getInstalledChaincodes() and getInstantiatedChaincodes() + chaincodes: + # the format follows the "cannonical name" of chaincodes by fabric code + - example02:v1 + - marbles:1.0 + +# +# list of participating organizations in this network +# +organizations: + Org1: + mspid: magnetocorpMSP + + peers: + - peer1.magnetocorp.com + + # [Optional]. Certificate Authorities issue certificates for identification purposes in a Fabric based + # network. Typically certificates provisioning is done in a separate process outside of the + # runtime network. Fabric-CA is a special certificate authority that provides a REST APIs for + # dynamic certificate management (enroll, revoke, re-enroll). The following section is only for + # Fabric-CA servers. + certificateAuthorities: + - ca-magnetocorp + + # [Optional]. If the application is going to make requests that are reserved to organization + # administrators, including creating/updating channels, installing/instantiating chaincodes, it + # must have access to the admin identity represented by the private key and signing certificate. + # Both properties can be the PEM string or local path to the PEM file. Note that this is mainly for + # convenience in development mode, production systems should not expose sensitive information + # this way. The SDK should allow applications to set the org admin identity via APIs, and only use + # this route as an alternative when it exists. + adminPrivateKey: + path: commercial-paper/organization/magnetocorp/users/Admin@magnetocorp/keystore/9022d671ceedbb24af3ea69b5a8136cc64203df6b9920e26f48123fcfcb1d2e9_sk + signedCert: + path: comercial-paper/organization/magnetocorp/users/Admin@magnetocorp.com/signcerts/Admin@magnetocorp.com-cert.pem + + # the profile will contain public information about organizations other than the one it belongs to. + # These are necessary information to make transaction lifecycles work, including MSP IDs and + # peers with a public URL to send transaction proposals. The file will not contain private + # information reserved for members of the organization, such as admin key and certificate, + # fabric-ca registrar enroll ID and secret, etc. + Org2: + mspid: digibankMSP + peers: + - peer1.digibank.com + certificateAuthorities: + - ca-digibank + adminPrivateKey: + path: commercial-paper/organization/digibank/users/Admin@digibank.com/keystore/5a983ddcbefe52a7f9b8ee5b85a590c3e3a43c4ccd70c7795bec504e7f74848d_sk + signedCert: + path: commercial-paper/organization/digibank/users/Admin@digibank.com/signcerts/Admin@digibank.com-cert.pem + +# +# List of orderers to send transaction and channel create/update requests to. For the time +# being only one orderer is needed. If more than one is defined, which one get used by the +# SDK is implementation specific. Consult each SDK's documentation for its handling of orderers. +# +orderers: + orderer.magnetocorp.com: + url: grpcs://localhost:7050 + + # these are standard properties defined by the gRPC library + # they will be passed in as-is to gRPC client constructor + grpcOptions: + ssl-target-name-override: orderer.example.com + + tlsCACerts: + path: comercial-paper/organization/magnetocorp/orderer/orderer.magnetocorp.com/tlscacerts/example.com-cert.pem + +# +# List of peers to send various requests to, including endorsement, query +# and event listener registration. +# +peers: + peer1.magnetocorp.com: + # this URL is used to send endorsement and query requests + url: grpcs://localhost:7051 + + grpcOptions: + ssl-target-name-override: peer1.magnetocorp.com + request-timeout: 120 + + tlsCACerts: + path: certificates/magnetocorp/magnetocorp.com-cert.pem + + peer1.digibank.com: + url: grpcs://localhost:8051 + grpcOptions: + ssl-target-name-override: peer1.digibank.com + tlsCACerts: + path: certificates/digibank/digibank.com-cert.pem + +# +# Fabric-CA is a special kind of Certificate Authority provided by Hyperledger Fabric which allows +# certificate management to be done via REST APIs. Application may choose to use a standard +# Certificate Authority instead of Fabric-CA, in which case this section would not be specified. +# +certificateAuthorities: + ca-org1: + url: https://localhost:7054 + # the properties specified under this object are passed to the 'http' client verbatim when + # making the request to the Fabric-CA server + httpOptions: + verify: false + tlsCACerts: + path: commercial-paper/organization/magnetocorp/ca/magnetocorp.com-cert.pem + + # Fabric-CA supports dynamic user enrollment via REST APIs. A "root" user, a.k.a registrar, is + # needed to enroll and invoke new users. + registrar: + - enrollId: admin + enrollSecret: adminpw + # [Optional] The optional name of the CA. + caName: ca-magnetocorp + + ca-org2: + url: https://localhost:8054 + httpOptions: + verify: false + tlsCACerts: + path: commercial-paper/organization/digibank/ca/digibank.com-cert.pem + registrar: + - enrollId: admin + enrollSecret: adminpw + # [Optional] The optional name of the CA. + caName: ca-digibank \ No newline at end of file From 9facb4256bc18adf57fb6e4b0562f15552febf0b Mon Sep 17 00:00:00 2001 From: Simon Stone Date: Thu, 15 Nov 2018 10:47:50 +0000 Subject: [PATCH 34/35] [FAB-12851] Add fabcar contract w/ new prog model (JS) Add new FabCar contract sample using the new programming model, written in JavaScript. Add the new contract sample alongside the existing one written in the old programming model, which will be removed in a subsequent change request. Change-Id: Iea46b0a616dbd072b5bd7227ada827a26560f153 Signed-off-by: Simon Stone --- chaincode/fabcar/javascript/.editorconfig | 16 +++ chaincode/fabcar/javascript/.eslintignore | 5 + chaincode/fabcar/javascript/.eslintrc.js | 38 ++++++ chaincode/fabcar/javascript/.gitignore | 77 +++++++++++ chaincode/fabcar/javascript/index.js | 10 ++ chaincode/fabcar/javascript/lib/fabcar.js | 156 ++++++++++++++++++++++ chaincode/fabcar/javascript/package.json | 47 +++++++ 7 files changed, 349 insertions(+) create mode 100755 chaincode/fabcar/javascript/.editorconfig create mode 100644 chaincode/fabcar/javascript/.eslintignore create mode 100644 chaincode/fabcar/javascript/.eslintrc.js create mode 100644 chaincode/fabcar/javascript/.gitignore create mode 100644 chaincode/fabcar/javascript/index.js create mode 100644 chaincode/fabcar/javascript/lib/fabcar.js create mode 100644 chaincode/fabcar/javascript/package.json diff --git a/chaincode/fabcar/javascript/.editorconfig b/chaincode/fabcar/javascript/.editorconfig new file mode 100755 index 00000000..75a13be2 --- /dev/null +++ b/chaincode/fabcar/javascript/.editorconfig @@ -0,0 +1,16 @@ +# +# SPDX-License-Identifier: Apache-2.0 +# + +root = true + +[*] +indent_style = space +indent_size = 4 +end_of_line = lf +charset = utf-8 +trim_trailing_whitespace = true +insert_final_newline = true + +[*.md] +trim_trailing_whitespace = false diff --git a/chaincode/fabcar/javascript/.eslintignore b/chaincode/fabcar/javascript/.eslintignore new file mode 100644 index 00000000..15958470 --- /dev/null +++ b/chaincode/fabcar/javascript/.eslintignore @@ -0,0 +1,5 @@ +# +# SPDX-License-Identifier: Apache-2.0 +# + +coverage diff --git a/chaincode/fabcar/javascript/.eslintrc.js b/chaincode/fabcar/javascript/.eslintrc.js new file mode 100644 index 00000000..6d5751a5 --- /dev/null +++ b/chaincode/fabcar/javascript/.eslintrc.js @@ -0,0 +1,38 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + */ + +module.exports = { + env: { + node: true, + mocha: true + }, + parserOptions: { + ecmaVersion: 8, + sourceType: 'script' + }, + extends: "eslint:recommended", + rules: { + indent: ['error', 4], + 'linebreak-style': ['error', 'unix'], + quotes: ['error', 'single'], + semi: ['error', 'always'], + 'no-unused-vars': ['error', { args: 'none' }], + 'no-console': 'off', + curly: 'error', + eqeqeq: 'error', + 'no-throw-literal': 'error', + strict: 'error', + 'no-var': 'error', + 'dot-notation': 'error', + 'no-tabs': 'error', + 'no-trailing-spaces': 'error', + 'no-use-before-define': 'error', + 'no-useless-call': 'error', + 'no-with': 'error', + 'operator-linebreak': 'error', + yoda: 'error', + 'quote-props': ['error', 'as-needed'], + 'no-constant-condition': ["error", { "checkLoops": false }] + } +}; diff --git a/chaincode/fabcar/javascript/.gitignore b/chaincode/fabcar/javascript/.gitignore new file mode 100644 index 00000000..a00ca941 --- /dev/null +++ b/chaincode/fabcar/javascript/.gitignore @@ -0,0 +1,77 @@ +# +# SPDX-License-Identifier: Apache-2.0 +# + +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* + +# Runtime data +pids +*.pid +*.seed +*.pid.lock + +# Directory for instrumented libs generated by jscoverage/JSCover +lib-cov + +# Coverage directory used by tools like istanbul +coverage + +# nyc test coverage +.nyc_output + +# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) +.grunt + +# Bower dependency directory (https://bower.io/) +bower_components + +# node-waf configuration +.lock-wscript + +# Compiled binary addons (https://nodejs.org/api/addons.html) +build/Release + +# Dependency directories +node_modules/ +jspm_packages/ + +# TypeScript v1 declaration files +typings/ + +# Optional npm cache directory +.npm + +# Optional eslint cache +.eslintcache + +# Optional REPL history +.node_repl_history + +# Output of 'npm pack' +*.tgz + +# Yarn Integrity file +.yarn-integrity + +# dotenv environment variables file +.env + +# parcel-bundler cache (https://parceljs.org/) +.cache + +# next.js build output +.next + +# nuxt.js build output +.nuxt + +# vuepress build output +.vuepress/dist + +# Serverless directories +.serverless diff --git a/chaincode/fabcar/javascript/index.js b/chaincode/fabcar/javascript/index.js new file mode 100644 index 00000000..f5911c8c --- /dev/null +++ b/chaincode/fabcar/javascript/index.js @@ -0,0 +1,10 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + */ + +'use strict'; + +const FabCar = require('./lib/fabcar'); + +module.exports.FabCar = FabCar; +module.exports.contracts = [ FabCar ]; diff --git a/chaincode/fabcar/javascript/lib/fabcar.js b/chaincode/fabcar/javascript/lib/fabcar.js new file mode 100644 index 00000000..53f2faef --- /dev/null +++ b/chaincode/fabcar/javascript/lib/fabcar.js @@ -0,0 +1,156 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + */ + +'use strict'; + +const { Contract } = require('fabric-contract-api'); + +class FabCar extends Contract { + + async initLedger(ctx) { + console.info('============= START : Initialize Ledger ==========='); + const cars = [ + { + color: 'blue', + make: 'Toyota', + model: 'Prius', + owner: 'Tomoko', + }, + { + color: 'red', + make: 'Ford', + model: 'Mustang', + owner: 'Brad', + }, + { + color: 'green', + make: 'Hyundai', + model: 'Tucson', + owner: 'Jin Soo', + }, + { + color: 'yellow', + make: 'Volkswagen', + model: 'Passat', + owner: 'Max', + }, + { + color: 'black', + make: 'Tesla', + model: 'S', + owner: 'Adriana', + }, + { + color: 'purple', + make: 'Peugeot', + model: '205', + owner: 'Michel', + }, + { + color: 'white', + make: 'Chery', + model: 'S22L', + owner: 'Aarav', + }, + { + color: 'violet', + make: 'Fiat', + model: 'Punto', + owner: 'Pari', + }, + { + color: 'indigo', + make: 'Tata', + model: 'Nano', + owner: 'Valeria', + }, + { + color: 'brown', + make: 'Holden', + model: 'Barina', + owner: 'Shotaro', + }, + ]; + + for (let i = 0; i < cars.length; i++) { + cars[i].docType = 'car'; + await ctx.stub.putState('CAR' + i, Buffer.from(JSON.stringify(cars[i]))); + console.info('Added <--> ', cars[i]); + } + console.info('============= END : Initialize Ledger ==========='); + } + + async queryCar(ctx, carNumber) { + const carAsBytes = await ctx.stub.getState(carNumber); // get the car from chaincode state + if (!carAsBytes || carAsBytes.length === 0) { + throw new Error(`${carNumber} does not exist`); + } + console.log(carAsBytes.toString()); + return carAsBytes.toString(); + } + + async createCar(ctx, carNumber, make, model, color, owner) { + console.info('============= START : Create Car ==========='); + + const car = { + color, + docType: 'car', + make, + model, + owner, + }; + + await ctx.stub.putState(carNumber, Buffer.from(JSON.stringify(car))); + console.info('============= END : Create Car ==========='); + } + + async queryAllCars(ctx) { + const startKey = 'CAR0'; + const endKey = 'CAR999'; + + const iterator = await ctx.stub.getStateByRange(startKey, endKey); + + const allResults = []; + while (true) { + const res = await iterator.next(); + + if (res.value && res.value.value.toString()) { + console.log(res.value.value.toString('utf8')); + + const Key = res.value.key; + let Record; + try { + Record = JSON.parse(res.value.value.toString('utf8')); + } catch (err) { + console.log(err); + Record = res.value.value.toString('utf8'); + } + allResults.push({ Key, Record }); + } + if (res.done) { + console.log('end of data'); + await iterator.close(); + console.info(allResults); + return JSON.stringify(allResults); + } + } + } + + async changeCarOwner(ctx, carNumber, newOwner) { + console.info('============= START : changeCarOwner ==========='); + + const carAsBytes = await ctx.stub.getState(carNumber); // get the car from chaincode state + if (!carAsBytes || carAsBytes.length === 0) { + throw new Error(`${carNumber} does not exist`); + } + const car = JSON.parse(carAsBytes.toString()); + car.owner = newOwner; + + await ctx.stub.putState(carNumber, Buffer.from(JSON.stringify(car))); + console.info('============= END : changeCarOwner ==========='); + } + +} + +module.exports = FabCar; diff --git a/chaincode/fabcar/javascript/package.json b/chaincode/fabcar/javascript/package.json new file mode 100644 index 00000000..2f9b98fb --- /dev/null +++ b/chaincode/fabcar/javascript/package.json @@ -0,0 +1,47 @@ +{ + "name": "fabcar", + "version": "1.0.0", + "description": "FabCar contract implemented in JavaScript", + "main": "index.js", + "engines": { + "node": ">=8", + "npm": ">=5" + }, + "scripts": { + "lint": "eslint .", + "pretest": "npm run lint", + "test": "nyc mocha --recursive", + "start": "fabric-chaincode-node start" + }, + "engineStrict": true, + "author": "Hyperledger", + "license": "Apache-2.0", + "dependencies": { + "fabric-contract-api": "1.4.0-beta", + "fabric-shim": "1.4.0-beta" + }, + "devDependencies": { + "chai": "^4.1.2", + "eslint": "^4.19.1", + "mocha": "^5.2.0", + "nyc": "^12.0.2", + "sinon": "^6.0.0", + "sinon-chai": "^3.2.0" + }, + "nyc": { + "exclude": [ + "coverage/**", + "test/**" + ], + "reporter": [ + "text-summary", + "html" + ], + "all": true, + "check-coverage": true, + "statements": 100, + "branches": 100, + "functions": 100, + "lines": 100 + } +} From 4fb3b57e6b6ed8a977fac679d5d512386b32c7c7 Mon Sep 17 00:00:00 2001 From: Simon Stone Date: Thu, 15 Nov 2018 10:44:02 +0000 Subject: [PATCH 35/35] [FAB-12852] Add fabcar contract w/ new prog model (TS) Add new FabCar contract sample using the new programming model, written in TypeScript. Add the new contract sample alongside the existing one written in the old programming model, which will be removed in a subsequent change request. Change-Id: I47e5f16b475c68f9a1c4752af2623f090fbf12c9 Signed-off-by: Simon Stone --- chaincode/fabcar/typescript/.editorconfig | 16 +++ chaincode/fabcar/typescript/.gitignore | 81 ++++++++++++ chaincode/fabcar/typescript/package.json | 62 +++++++++ chaincode/fabcar/typescript/src/car.ts | 11 ++ chaincode/fabcar/typescript/src/fabcar.ts | 153 ++++++++++++++++++++++ chaincode/fabcar/typescript/src/index.ts | 8 ++ chaincode/fabcar/typescript/tsconfig.json | 16 +++ chaincode/fabcar/typescript/tslint.json | 21 +++ 8 files changed, 368 insertions(+) create mode 100755 chaincode/fabcar/typescript/.editorconfig create mode 100644 chaincode/fabcar/typescript/.gitignore create mode 100644 chaincode/fabcar/typescript/package.json create mode 100644 chaincode/fabcar/typescript/src/car.ts create mode 100644 chaincode/fabcar/typescript/src/fabcar.ts create mode 100644 chaincode/fabcar/typescript/src/index.ts create mode 100644 chaincode/fabcar/typescript/tsconfig.json create mode 100644 chaincode/fabcar/typescript/tslint.json diff --git a/chaincode/fabcar/typescript/.editorconfig b/chaincode/fabcar/typescript/.editorconfig new file mode 100755 index 00000000..75a13be2 --- /dev/null +++ b/chaincode/fabcar/typescript/.editorconfig @@ -0,0 +1,16 @@ +# +# SPDX-License-Identifier: Apache-2.0 +# + +root = true + +[*] +indent_style = space +indent_size = 4 +end_of_line = lf +charset = utf-8 +trim_trailing_whitespace = true +insert_final_newline = true + +[*.md] +trim_trailing_whitespace = false diff --git a/chaincode/fabcar/typescript/.gitignore b/chaincode/fabcar/typescript/.gitignore new file mode 100644 index 00000000..69d6a33b --- /dev/null +++ b/chaincode/fabcar/typescript/.gitignore @@ -0,0 +1,81 @@ +# +# SPDX-License-Identifier: Apache-2.0 +# + +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* + +# Runtime data +pids +*.pid +*.seed +*.pid.lock + +# Directory for instrumented libs generated by jscoverage/JSCover +lib-cov + +# Coverage directory used by tools like istanbul +coverage + +# nyc test coverage +.nyc_output + +# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) +.grunt + +# Bower dependency directory (https://bower.io/) +bower_components + +# node-waf configuration +.lock-wscript + +# Compiled binary addons (https://nodejs.org/api/addons.html) +build/Release + +# Dependency directories +node_modules/ +jspm_packages/ + +# TypeScript v1 declaration files +typings/ + +# Optional npm cache directory +.npm + +# Optional eslint cache +.eslintcache + +# Optional REPL history +.node_repl_history + +# Output of 'npm pack' +*.tgz + +# Yarn Integrity file +.yarn-integrity + +# dotenv environment variables file +.env + +# parcel-bundler cache (https://parceljs.org/) +.cache + +# next.js build output +.next + +# nuxt.js build output +.nuxt + +# vuepress build output +.vuepress/dist + +# Serverless directories +.serverless + +# Compiled TypeScript files +dist + diff --git a/chaincode/fabcar/typescript/package.json b/chaincode/fabcar/typescript/package.json new file mode 100644 index 00000000..45e96de8 --- /dev/null +++ b/chaincode/fabcar/typescript/package.json @@ -0,0 +1,62 @@ +{ + "name": "fabcar", + "version": "1.0.0", + "description": "FabCar contract implemented in TypeScript", + "main": "dist/index.js", + "typings": "dist/index.d.ts", + "engines": { + "node": ">=8", + "npm": ">=5" + }, + "scripts": { + "lint": "tslint -c tslint.json 'src/**/*.ts'", + "pretest": "npm run lint", + "test": "nyc mocha -r ts-node/register src/**/*.spec.ts", + "start": "fabric-chaincode-node start", + "build": "tsc", + "build:watch": "tsc -w", + "prepublishOnly": "npm run build" + }, + "engineStrict": true, + "author": "Hyperledger", + "license": "Apache-2.0", + "dependencies": { + "fabric-contract-api": "1.4.0-beta", + "fabric-shim": "1.4.0-beta" + }, + "devDependencies": { + "@types/chai": "^4.1.4", + "@types/mocha": "^5.2.3", + "@types/node": "^10.3.6", + "@types/sinon": "^5.0.1", + "@types/sinon-chai": "^3.2.0", + "chai": "^4.1.2", + "mocha": "^5.2.0", + "nyc": "^12.0.2", + "sinon": "^6.0.0", + "sinon-chai": "^3.2.0", + "ts-node": "^7.0.0", + "tslint": "^5.10.0", + "typescript": "^2.9.2" + }, + "nyc": { + "extension": [ + ".ts", + ".tsx" + ], + "exclude": [ + "coverage/**", + "dist/**" + ], + "reporter": [ + "text-summary", + "html" + ], + "all": true, + "check-coverage": true, + "statements": 100, + "branches": 100, + "functions": 100, + "lines": 100 + } +} diff --git a/chaincode/fabcar/typescript/src/car.ts b/chaincode/fabcar/typescript/src/car.ts new file mode 100644 index 00000000..ba101625 --- /dev/null +++ b/chaincode/fabcar/typescript/src/car.ts @@ -0,0 +1,11 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + */ + +export class Car { + public docType?: string; + public color: string; + public make: string; + public model: string; + public owner: string; +} diff --git a/chaincode/fabcar/typescript/src/fabcar.ts b/chaincode/fabcar/typescript/src/fabcar.ts new file mode 100644 index 00000000..de72b039 --- /dev/null +++ b/chaincode/fabcar/typescript/src/fabcar.ts @@ -0,0 +1,153 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + */ + +import { Context, Contract } from 'fabric-contract-api'; +import { Car } from './car'; + +export class FabCar extends Contract { + + public async initLedger(ctx: Context) { + console.info('============= START : Initialize Ledger ==========='); + const cars: Car[] = [ + { + color: 'blue', + make: 'Toyota', + model: 'Prius', + owner: 'Tomoko', + }, + { + color: 'red', + make: 'Ford', + model: 'Mustang', + owner: 'Brad', + }, + { + color: 'green', + make: 'Hyundai', + model: 'Tucson', + owner: 'Jin Soo', + }, + { + color: 'yellow', + make: 'Volkswagen', + model: 'Passat', + owner: 'Max', + }, + { + color: 'black', + make: 'Tesla', + model: 'S', + owner: 'Adriana', + }, + { + color: 'purple', + make: 'Peugeot', + model: '205', + owner: 'Michel', + }, + { + color: 'white', + make: 'Chery', + model: 'S22L', + owner: 'Aarav', + }, + { + color: 'violet', + make: 'Fiat', + model: 'Punto', + owner: 'Pari', + }, + { + color: 'indigo', + make: 'Tata', + model: 'Nano', + owner: 'Valeria', + }, + { + color: 'brown', + make: 'Holden', + model: 'Barina', + owner: 'Shotaro', + }, + ]; + + for (let i = 0; i < cars.length; i++) { + cars[i].docType = 'car'; + await ctx.stub.putState('CAR' + i, Buffer.from(JSON.stringify(cars[i]))); + console.info('Added <--> ', cars[i]); + } + console.info('============= END : Initialize Ledger ==========='); + } + + public async queryCar(ctx: Context, carNumber: string): Promise { + const carAsBytes = await ctx.stub.getState(carNumber); // get the car from chaincode state + if (!carAsBytes || carAsBytes.length === 0) { + throw new Error(`${carNumber} does not exist`); + } + console.log(carAsBytes.toString()); + return carAsBytes.toString(); + } + + public async createCar(ctx: Context, carNumber: string, make: string, model: string, color: string, owner: string) { + console.info('============= START : Create Car ==========='); + + const car: Car = { + color, + docType: 'car', + make, + model, + owner, + }; + + await ctx.stub.putState(carNumber, Buffer.from(JSON.stringify(car))); + console.info('============= END : Create Car ==========='); + } + + public async queryAllCars(ctx: Context): Promise { + const startKey = 'CAR0'; + const endKey = 'CAR999'; + + const iterator = await ctx.stub.getStateByRange(startKey, endKey); + + const allResults = []; + while (true) { + const res = await iterator.next(); + + if (res.value && res.value.value.toString()) { + console.log(res.value.value.toString('utf8')); + + const Key = res.value.key; + let Record; + try { + Record = JSON.parse(res.value.value.toString('utf8')); + } catch (err) { + console.log(err); + Record = res.value.value.toString('utf8'); + } + allResults.push({ Key, Record }); + } + if (res.done) { + console.log('end of data'); + await iterator.close(); + console.info(allResults); + return JSON.stringify(allResults); + } + } + } + + public async changeCarOwner(ctx: Context, carNumber: string, newOwner: string) { + console.info('============= START : changeCarOwner ==========='); + + const carAsBytes = await ctx.stub.getState(carNumber); // get the car from chaincode state + if (!carAsBytes || carAsBytes.length === 0) { + throw new Error(`${carNumber} does not exist`); + } + const car: Car = JSON.parse(carAsBytes.toString()); + car.owner = newOwner; + + await ctx.stub.putState(carNumber, Buffer.from(JSON.stringify(car))); + console.info('============= END : changeCarOwner ==========='); + } + +} diff --git a/chaincode/fabcar/typescript/src/index.ts b/chaincode/fabcar/typescript/src/index.ts new file mode 100644 index 00000000..c0a2fcf6 --- /dev/null +++ b/chaincode/fabcar/typescript/src/index.ts @@ -0,0 +1,8 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + */ + +import { FabCar } from './fabcar'; +export { FabCar } from './fabcar'; + +export const contracts: any[] = [ FabCar ]; diff --git a/chaincode/fabcar/typescript/tsconfig.json b/chaincode/fabcar/typescript/tsconfig.json new file mode 100644 index 00000000..8c96ea07 --- /dev/null +++ b/chaincode/fabcar/typescript/tsconfig.json @@ -0,0 +1,16 @@ +{ + "compilerOptions": { + "outDir": "dist", + "target": "es2017", + "moduleResolution": "node", + "module": "commonjs", + "declaration": true, + "sourceMap": true + }, + "include": [ + "./src/**/*" + ], + "exclude": [ + "./src/**/*.spec.ts" + ] +} diff --git a/chaincode/fabcar/typescript/tslint.json b/chaincode/fabcar/typescript/tslint.json new file mode 100644 index 00000000..33ccbf3c --- /dev/null +++ b/chaincode/fabcar/typescript/tslint.json @@ -0,0 +1,21 @@ +{ + "defaultSeverity": "error", + "extends": [ + "tslint:recommended" + ], + "jsRules": {}, + "rules": { + "indent": [true, "spaces", 4], + "linebreak-style": [true, "LF"], + "quotemark": [true, "single"], + "semicolon": [true, "always"], + "no-console": false, + "curly": true, + "triple-equals": true, + "no-string-throw": true, + "no-var-keyword": true, + "no-trailing-whitespace": true, + "object-literal-key-quotes": [true, "as-needed"] + }, + "rulesDirectory": [] +}