From 86c194615df33d32c66e13b1434be59a6a638b21 Mon Sep 17 00:00:00 2001 From: NIKHIL E GUPTA Date: Tue, 9 Jun 2020 08:54:08 -0400 Subject: [PATCH] Update private data marbes for smart contract api Signed-off-by: NIKHIL E GUPTA --- chaincode/marbles02_private/go/go.mod | 11 +- chaincode/marbles02_private/go/go.sum | 140 +++-- .../go/marbles_chaincode_private.go | 545 +++++++----------- 3 files changed, 307 insertions(+), 389 deletions(-) diff --git a/chaincode/marbles02_private/go/go.mod b/chaincode/marbles02_private/go/go.mod index f9eff013..86745398 100644 --- a/chaincode/marbles02_private/go/go.mod +++ b/chaincode/marbles02_private/go/go.mod @@ -1,12 +1,5 @@ module github.com/hyperledger/fabric-samples/chaincode/marbles02_private/go -go 1.12 +go 1.13 -require ( - github.com/hyperledger/fabric-chaincode-go v0.0.0-20190823162523-04390e015b85 - github.com/hyperledger/fabric-protos-go v0.0.0-20190821214336-621b908d5022 - golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7 // indirect - golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a // indirect - golang.org/x/text v0.3.2 // indirect - google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55 // indirect -) +require github.com/hyperledger/fabric-contract-api-go v1.1.0 diff --git a/chaincode/marbles02_private/go/go.sum b/chaincode/marbles02_private/go/go.sum index 66ba37b6..653dbb08 100644 --- a/chaincode/marbles02_private/go/go.sum +++ b/chaincode/marbles02_private/go/go.sum @@ -1,85 +1,137 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/DATA-DOG/go-txdb v0.1.3/go.mod h1:DhAhxMXZpUJVGnT+p9IbzJoRKvlArO2pkHjnGX7o0n0= +github.com/PuerkitoBio/purell v1.1.1 h1:WEQqlqaGbrPkxLJWfBwQmfEAE1Z7ONdDLqrN38tNFfI= +github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= +github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 h1:d+Bc7a5rLufV/sSk/8dngufqelfh6jnri85riMAaF/M= +github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= +github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= -github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= +github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= +github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk= +github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= +github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= +github.com/cucumber/godog v0.8.0/go.mod h1:Cp3tEV1LRAyH/RuCThcxHS/+9ORZ+FMzPva2AZ5Ki+A= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/gogo/protobuf v1.2.1 h1:/s5zKNz0uPFCZ5hddgPdo2TK2TVrUNMn0OOX8/aZMTE= -github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= -github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58= +github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= +github.com/go-openapi/jsonpointer v0.19.2/go.mod h1:3akKfEdA7DF1sugOqz1dVQHBcuDBPKZGEoHC/NkiQRg= +github.com/go-openapi/jsonpointer v0.19.3 h1:gihV7YNZK1iK6Tgwwsxo2rJbD1GTbdm72325Bq8FI3w= +github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= +github.com/go-openapi/jsonreference v0.19.2 h1:o20suLFB4Ri0tuzpWtyHlh7E7HnkqTNLq6aR6WVNS1w= +github.com/go-openapi/jsonreference v0.19.2/go.mod h1:jMjeRr2HHw6nAVajTXJ4eiUwohSTlpa0o73RUL1owJc= +github.com/go-openapi/spec v0.19.4 h1:ixzUSnHTd6hCemgtAJgluaTSGYpLNpJY4mA2DIkdOAo= +github.com/go-openapi/spec v0.19.4/go.mod h1:FpwSN1ksY1eteniUU7X0N/BgJ7a4WvBFVA8Lj9mJglo= +github.com/go-openapi/swag v0.19.2/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= +github.com/go-openapi/swag v0.19.5 h1:lTz6Ys4CmqqCQmZPBlbQENR1/GucA2bzYTE12Pw4tFY= +github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= +github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= +github.com/gobuffalo/envy v1.7.0 h1:GlXgaiBkmrYMHco6t4j7SacKO4XUjvh5pwXh0f4uxXU= +github.com/gobuffalo/envy v1.7.0/go.mod h1:n7DRkBerg/aorDM8kbduw5dN3oXGswK5liaSCx4T5NI= +github.com/gobuffalo/logger v1.0.0/go.mod h1:2zbswyIUa45I+c+FLXuWl9zSWEiVuthsk8ze5s8JvPs= +github.com/gobuffalo/packd v0.3.0 h1:eMwymTkA1uXsqxS0Tpoop3Lc0u3kTfiMBE6nKtQU4g4= +github.com/gobuffalo/packd v0.3.0/go.mod h1:zC7QkmNkYVGKPw4tHpBQ+ml7W/3tIebgeo1b36chA3Q= +github.com/gobuffalo/packr v1.30.1 h1:hu1fuVR3fXEZR7rXNW3h8rqSML8EVAf6KNm0NKO/wKg= +github.com/gobuffalo/packr v1.30.1/go.mod h1:ljMyFO2EcrnzsHsN99cvbq055Y9OhRrIaviy289eRuk= +github.com/gobuffalo/packr/v2 v2.5.1/go.mod h1:8f9c96ITobJlPzI44jj+4tHnEKNt0xXWSVlXRN9X1Iw= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= -github.com/hyperledger/fabric-chaincode-go v0.0.0-20190823162523-04390e015b85 h1:VEm3tPRTCzq3J/1XpVERh1PbOSnshUVwx2G5s3cLiTw= -github.com/hyperledger/fabric-chaincode-go v0.0.0-20190823162523-04390e015b85/go.mod h1:HZK6PKLWrvdD/t0oSLiyaRaUM6fZ7qjJuOlb0zrn0mo= -github.com/hyperledger/fabric-protos-go v0.0.0-20190821214336-621b908d5022 h1:WzttYAPO5xkQ87ZrxzEhvDZknfarSNu1PZt3NPMTE3Y= -github.com/hyperledger/fabric-protos-go v0.0.0-20190821214336-621b908d5022/go.mod h1:xVYTjK4DtZRBxZ2D9aE4y6AbLaPwue2o/criQyQbVD0= -github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= -github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= +github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= +github.com/hyperledger/fabric-chaincode-go v0.0.0-20200424173110-d7076418f212 h1:1i4lnpV8BDgKOLi1hgElfBqdHXjXieSuj8629mwBZ8o= +github.com/hyperledger/fabric-chaincode-go v0.0.0-20200424173110-d7076418f212/go.mod h1:N7H3sA7Tx4k/YzFq7U0EPdqJtqvM4Kild0JoCc7C0Dc= +github.com/hyperledger/fabric-contract-api-go v1.1.0 h1:K9uucl/6eX3NF0/b+CGIiO1IPm1VYQxBkpnVGJur2S4= +github.com/hyperledger/fabric-contract-api-go v1.1.0/go.mod h1:nHWt0B45fK53owcFpLtAe8DH0Q5P068mnzkNXMPSL7E= +github.com/hyperledger/fabric-protos-go v0.0.0-20190919234611-2a87503ac7c9/go.mod h1:xVYTjK4DtZRBxZ2D9aE4y6AbLaPwue2o/criQyQbVD0= +github.com/hyperledger/fabric-protos-go v0.0.0-20200424173316-dd554ba3746e h1:9PS5iezHk/j7XriSlNuSQILyCOfcZ9wZ3/PiucmSE8E= +github.com/hyperledger/fabric-protos-go v0.0.0-20200424173316-dd554ba3746e/go.mod h1:xVYTjK4DtZRBxZ2D9aE4y6AbLaPwue2o/criQyQbVD0= +github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= +github.com/joho/godotenv v1.3.0 h1:Zjp+RcGpHhGlrMbJzXTrZZPrWj+1vfm90La1wgB6Bhc= +github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg= +github.com/karrick/godirwalk v1.10.12/go.mod h1:RoGL9dQei4vP9ilrpETWE8CLOZ1kiN0LhBygSwrAsHA= +github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= +github.com/kr/pty v1.1.5/go.mod h1:9r2w37qlBe7rQ6e1fg1S/9xpWHSnaqNdHD3WcMdbPDA= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= -github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= +github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= +github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e h1:hB2xlXdHp/pmPZq0y3QnmWAArdw9PqbmotexnWx/FU8= +github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= +github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= +github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/stretchr/objx v0.1.0 h1:4G4v2dO3VZwixGIRoQ5Lfboy6nUhCyYzaqnIAPPhYs4= +github.com/rogpeppe/go-internal v1.1.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= +github.com/rogpeppe/go-internal v1.3.0 h1:RR9dF3JtopPvtkroDZuVD7qquD0bnHlKSqaQhgwt8yk= +github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= +github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= +github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= +github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= +github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= +github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU= +github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= +github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk= +github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= +github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= +github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f h1:J9EGpcZtP0E/raorCMxlFGSTBrsSlaDGf3jU/qvAE2c= +github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= +github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHovont7NscjpAxXsDA8S8BMYve8Y5+7cuRE7R0= +github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= +github.com/xeipuuv/gojsonschema v1.2.0 h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17UxZ74= +github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= +github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= +golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= -golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= +golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190621222207-cc06ce4a13d4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190522155817-f3200d17e092 h1:4QSRKanuywn15aTZvI/mIDEgPQpswuFndXpOj3rKEco= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= -golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7 h1:fHDIZ2oxGnUZRN6WgWFCbYBjH9uqVPRCUVUDhs0wnbA= -golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297 h1:k7pJ2yAPLPgbskkFdhRCsA77k2fySZ1zf2zCjvQCiIM= +golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= -golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190515120540-06a5c4944438/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190616124812-15dcb6c0061f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190710143415-6ec70d6a5542/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a h1:aYOabOQFp6Vj6W1F80affTUvO9UxmJRx8K0gsfABByQ= -golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= -golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190614205625-5aca471b1d59/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190624180213-70d37148ca0c/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= -google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8 h1:Nw54tB0rB7hY/N0NQvRW8DG4Yk3Q6T9cu9RcFQDu1tc= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20180831171423-11092d34479b h1:lohp5blsw53GBXtLyLNaTXPXS9pJ1tiTw61ZHUoE9Qw= google.golang.org/genproto v0.0.0-20180831171423-11092d34479b/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= -google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55 h1:gSJIx1SDwno+2ElGhA4+qG2zF97qiUzTM+rQ0klBOcE= -google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= -google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.23.0 h1:AzbTB6ux+okLTzP8Ru1Xs41C303zdcfEht7MQnYJt5A= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10= +gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= diff --git a/chaincode/marbles02_private/go/marbles_chaincode_private.go b/chaincode/marbles02_private/go/marbles_chaincode_private.go index b96b040e..34d5e1be 100644 --- a/chaincode/marbles02_private/go/marbles_chaincode_private.go +++ b/chaincode/marbles02_private/go/marbles_chaincode_private.go @@ -9,31 +9,31 @@ SPDX-License-Identifier: Apache-2.0 // ==== Invoke marbles, pass private data as base64 encoded bytes in transient map ==== // // export MARBLE=$(echo -n "{\"name\":\"marble1\",\"color\":\"blue\",\"size\":35,\"owner\":\"tom\",\"price\":99}" | base64 | tr -d \\n) -// peer chaincode invoke -C mychannel -n marblesp -c '{"Args":["initMarble"]}' --transient "{\"marble\":\"$MARBLE\"}" +// peer chaincode invoke -C mychannel -n marblesp -c '{"Args":["InitMarble"]}' --transient "{\"marble\":\"$MARBLE\"}" // // export MARBLE=$(echo -n "{\"name\":\"marble2\",\"color\":\"red\",\"size\":50,\"owner\":\"tom\",\"price\":102}" | base64 | tr -d \\n) -// peer chaincode invoke -C mychannel -n marblesp -c '{"Args":["initMarble"]}' --transient "{\"marble\":\"$MARBLE\"}" +// peer chaincode invoke -C mychannel -n marblesp -c '{"Args":["InitMarble"]}' --transient "{\"marble\":\"$MARBLE\"}" // // export MARBLE=$(echo -n "{\"name\":\"marble3\",\"color\":\"blue\",\"size\":70,\"owner\":\"tom\",\"price\":103}" | base64 | tr -d \\n) -// peer chaincode invoke -C mychannel -n marblesp -c '{"Args":["initMarble"]}' --transient "{\"marble\":\"$MARBLE\"}" +// peer chaincode invoke -C mychannel -n marblesp -c '{"Args":["InitMarble"]}' --transient "{\"marble\":\"$MARBLE\"}" // // export MARBLE_OWNER=$(echo -n "{\"name\":\"marble2\",\"owner\":\"jerry\"}" | base64 | tr -d \\n) -// peer chaincode invoke -C mychannel -n marblesp -c '{"Args":["transferMarble"]}' --transient "{\"marble_owner\":\"$MARBLE_OWNER\"}" +// peer chaincode invoke -C mychannel -n marblesp -c '{"Args":["TransferMarble"]}' --transient "{\"marble_owner\":\"$MARBLE_OWNER\"}" // // export MARBLE_DELETE=$(echo -n "{\"name\":\"marble1\"}" | base64 | tr -d \\n) -// peer chaincode invoke -C mychannel -n marblesp -c '{"Args":["delete"]}' --transient "{\"marble_delete\":\"$MARBLE_DELETE\"}" +// peer chaincode invoke -C mychannel -n marblesp -c '{"Args":["Delete"]}' --transient "{\"marble_delete\":\"$MARBLE_DELETE\"}" // ==== Query marbles, since queries are not recorded on chain we don't need to hide private data in transient map ==== -// peer chaincode query -C mychannel -n marblesp -c '{"Args":["readMarble","marble1"]}' -// peer chaincode query -C mychannel -n marblesp -c '{"Args":["readMarblePrivateDetails","marble1"]}' -// peer chaincode query -C mychannel -n marblesp -c '{"Args":["getMarblesByRange","marble1","marble4"]}' +// peer chaincode query -C mychannel -n marblesp -c '{"Args":["ReadMarble","marble1"]}' +// peer chaincode query -C mychannel -n marblesp -c '{"Args":["ReadMarblePrivateDetails","marble1"]}' +// peer chaincode query -C mychannel -n marblesp -c '{"Args":["GetMarblesByRange","marble1","marble4"]}' // Query a marble's public data hash -// peer chaincode query -C mychannel -n marblesp -c '{"Args":["getMarbleHash","collectionMarbles","marble1"]}' +// peer chaincode query -C mychannel -n marblesp -c '{"Args":["GetMarbleHash","collectionMarbles","marble1"]}' // Rich Query (Only supported if CouchDB is used as state database): -// peer chaincode query -C mychannel -n marblesp -c '{"Args":["queryMarblesByOwner","tom"]}' -// peer chaincode query -C mychannel -n marblesp -c '{"Args":["queryMarbles","{\"selector\":{\"owner\":\"tom\"}}"]}' +// peer chaincode query -C mychannel -n marblesp -c '{"Args":["QueryMarblesByOwner","tom"]}' +// peer chaincode query -C mychannel -n marblesp -c '{"Args":["QueryMarbles","{\"selector\":{\"owner\":\"tom\"}}"]}' // INDEXES TO SUPPORT COUCHDB RICH QUERIES // @@ -86,28 +86,22 @@ SPDX-License-Identifier: Apache-2.0 // {"index":{"fields":[{"data.size":"desc"},{"data.docType":"desc"},{"data.owner":"desc"}]},"ddoc":"indexSizeSortDoc", "name":"indexSizeSortDesc","type":"json"} // Rich Query with index design doc and index name specified (Only supported if CouchDB is used as state database): -// peer chaincode query -C mychannel -n marblesp -c '{"Args":["queryMarbles","{\"selector\":{\"docType\":\"marble\",\"owner\":\"tom\"}, \"use_index\":[\"_design/indexOwnerDoc\", \"indexOwner\"]}"]}' +// peer chaincode query -C mychannel -n marblesp -c '{"Args":["QueryMarbles","{\"selector\":{\"docType\":\"marble\",\"owner\":\"tom\"}, \"use_index\":[\"_design/indexOwnerDoc\", \"indexOwner\"]}"]}' // Rich Query with index design doc specified only (Only supported if CouchDB is used as state database): -// peer chaincode query -C mychannel -n marblesp -c '{"Args":["queryMarbles","{\"selector\":{\"docType\":{\"$eq\":\"marble\"},\"owner\":{\"$eq\":\"tom\"},\"size\":{\"$gt\":0}},\"fields\":[\"docType\",\"owner\",\"size\"],\"sort\":[{\"size\":\"desc\"}],\"use_index\":\"_design/indexSizeSortDoc\"}"]}' +// peer chaincode query -C mychannel -n marblesp -c '{"Args":["QueryMarbles","{\"selector\":{\"docType\":{\"$eq\":\"marble\"},\"owner\":{\"$eq\":\"tom\"},\"size\":{\"$gt\":0}},\"fields\":[\"docType\",\"owner\",\"size\"],\"sort\":[{\"size\":\"desc\"}],\"use_index\":\"_design/indexSizeSortDoc\"}"]}' package main import ( - "bytes" "encoding/json" "fmt" "strings" - "github.com/hyperledger/fabric-chaincode-go/shim" - pb "github.com/hyperledger/fabric-protos-go/peer" + "github.com/hyperledger/fabric-contract-api-go/contractapi" ) -// SimpleChaincode example simple Chaincode implementation -type SimpleChaincode struct { -} - -type marble struct { +type Marble struct { ObjectType string `json:"docType"` //docType is used to distinguish the various types of objects in state database Name string `json:"name"` //the fieldtags are needed to keep case from bouncing around Color string `json:"color"` @@ -115,75 +109,32 @@ type marble struct { Owner string `json:"owner"` } -type marblePrivateDetails struct { +type MarblePrivateDetails struct { ObjectType string `json:"docType"` //docType is used to distinguish the various types of objects in state database Name string `json:"name"` //the fieldtags are needed to keep case from bouncing around Price int `json:"price"` } -// =================================================================================== -// Main -// =================================================================================== -func main() { - err := shim.Start(new(SimpleChaincode)) - if err != nil { - fmt.Printf("Error starting Simple chaincode: %s", err) - } +type SmartContract struct { + contractapi.Contract } -// Init initializes chaincode -// =========================== -func (t *SimpleChaincode) Init(stub shim.ChaincodeStubInterface) pb.Response { - return shim.Success(nil) -} - -// Invoke - Our entry point for Invocations -// ======================================== -func (t *SimpleChaincode) Invoke(stub shim.ChaincodeStubInterface) pb.Response { - function, args := stub.GetFunctionAndParameters() - fmt.Println("invoke is running " + function) - - // Handle different functions - switch function { - case "initMarble": - //create a new marble - return t.initMarble(stub, args) - case "readMarble": - //read a marble - return t.readMarble(stub, args) - case "readMarblePrivateDetails": - //read a marble private details - return t.readMarblePrivateDetails(stub, args) - case "transferMarble": - //change owner of a specific marble - return t.transferMarble(stub, args) - case "delete": - //delete a marble - return t.delete(stub, args) - case "queryMarblesByOwner": - //find marbles for owner X using rich query - return t.queryMarblesByOwner(stub, args) - case "queryMarbles": - //find marbles based on an ad hoc rich query - return t.queryMarbles(stub, args) - case "getMarblesByRange": - //get marbles based on range query - return t.getMarblesByRange(stub, args) - case "getMarbleHash": - //verify a marble using the public hash - return t.getMarbleHash(stub, args) - default: - //error - fmt.Println("invoke did not find func: " + function) - return shim.Error("Received unknown function invocation") - } -} // ============================================================ // initMarble - create a new marble, store into chaincode state // ============================================================ -func (t *SimpleChaincode) initMarble(stub shim.ChaincodeStubInterface, args []string) pb.Response { - var err error +func (s *SmartContract) InitMarble(ctx contractapi.TransactionContextInterface) error { + + transMap, err := ctx.GetStub().GetTransient() + if err != nil { + return fmt.Errorf("Error getting transient: " + err.Error()) + } + + // Marble properties are private, therefore they get passed in transient field + transientMarbleJSON, ok := transMap["marble"] + if !ok { + return fmt.Errorf("marble not found in the transient map") + } type marbleTransientInput struct { Name string `json:"name"` //the fieldtags are needed to keep case from bouncing around @@ -193,61 +144,40 @@ func (t *SimpleChaincode) initMarble(stub shim.ChaincodeStubInterface, args []st Price int `json:"price"` } - // ==== Input sanitation ==== - fmt.Println("- start init marble") - - if len(args) != 0 { - return shim.Error("Incorrect number of arguments. Private marble data must be passed in transient map.") - } - - transMap, err := stub.GetTransient() - if err != nil { - return shim.Error("Error getting transient: " + err.Error()) - } - - marbleJsonBytes, ok := transMap["marble"] - if !ok { - return shim.Error("marble must be a key in the transient map") - } - - if len(marbleJsonBytes) == 0 { - return shim.Error("marble value in the transient map must be a non-empty JSON string") - } - var marbleInput marbleTransientInput - err = json.Unmarshal(marbleJsonBytes, &marbleInput) + err = json.Unmarshal(transientMarbleJSON, &marbleInput) if err != nil { - return shim.Error("Failed to decode JSON of: " + string(marbleJsonBytes)) + return fmt.Errorf("failed to unmarshal JSON: %s", err.Error()) } if len(marbleInput.Name) == 0 { - return shim.Error("name field must be a non-empty string") + return fmt.Errorf("name field must be a non-empty string") } if len(marbleInput.Color) == 0 { - return shim.Error("color field must be a non-empty string") + return fmt.Errorf("color field must be a non-empty string") } if marbleInput.Size <= 0 { - return shim.Error("size field must be a positive integer") + return fmt.Errorf("size field must be a positive integer") } if len(marbleInput.Owner) == 0 { - return shim.Error("owner field must be a non-empty string") + return fmt.Errorf("owner field must be a non-empty string") } if marbleInput.Price <= 0 { - return shim.Error("price field must be a positive integer") + return fmt.Errorf("price field must be a positive integer") } // ==== Check if marble already exists ==== - marbleAsBytes, err := stub.GetPrivateData("collectionMarbles", marbleInput.Name) + marbleAsBytes, err := ctx.GetStub().GetPrivateData("collectionMarbles", marbleInput.Name) if err != nil { - return shim.Error("Failed to get marble: " + err.Error()) + return fmt.Errorf("Failed to get marble: " + err.Error()) } else if marbleAsBytes != nil { fmt.Println("This marble already exists: " + marbleInput.Name) - return shim.Error("This marble already exists: " + marbleInput.Name) + return fmt.Errorf("This marble already exists: " + marbleInput.Name) } // ==== Create marble object, marshal to JSON, and save to state ==== - marble := &marble{ - ObjectType: "marble", + marble := &Marble{ + ObjectType: "Marble", Name: marbleInput.Name, Color: marbleInput.Color, Size: marbleInput.Size, @@ -255,28 +185,28 @@ func (t *SimpleChaincode) initMarble(stub shim.ChaincodeStubInterface, args []st } marbleJSONasBytes, err := json.Marshal(marble) if err != nil { - return shim.Error(err.Error()) + return fmt.Errorf(err.Error()) } // === Save marble to state === - err = stub.PutPrivateData("collectionMarbles", marbleInput.Name, marbleJSONasBytes) + err = ctx.GetStub().PutPrivateData("collectionMarbles", marbleInput.Name, marbleJSONasBytes) if err != nil { - return shim.Error(err.Error()) + return fmt.Errorf("failed to put Marble: %s", err.Error()) } // ==== Create marble private details object with price, marshal to JSON, and save to state ==== - marblePrivateDetails := &marblePrivateDetails{ - ObjectType: "marblePrivateDetails", + marblePrivateDetails := &MarblePrivateDetails{ + ObjectType: "MarblePrivateDetails", Name: marbleInput.Name, Price: marbleInput.Price, } - marblePrivateDetailsBytes, err := json.Marshal(marblePrivateDetails) + marblePrivateDetailsAsBytes, err := json.Marshal(marblePrivateDetails) if err != nil { - return shim.Error(err.Error()) + return fmt.Errorf(err.Error()) } - err = stub.PutPrivateData("collectionMarblePrivateDetails", marbleInput.Name, marblePrivateDetailsBytes) + err = ctx.GetStub().PutPrivateData("collectionMarblePrivateDetails", marbleInput.Name, marblePrivateDetailsAsBytes) if err != nil { - return shim.Error(err.Error()) + return fmt.Errorf("failed to put Marble private details: %s", err.Error()) } // ==== Index the marble to enable color-based range queries, e.g. return all blue marbles ==== @@ -285,211 +215,191 @@ func (t *SimpleChaincode) initMarble(stub shim.ChaincodeStubInterface, args []st // In our case, the composite key is based on indexName=color~name. // This will enable very efficient state range queries based on composite keys matching indexName=color~* indexName := "color~name" - colorNameIndexKey, err := stub.CreateCompositeKey(indexName, []string{marble.Color, marble.Name}) + colorNameIndexKey, err := ctx.GetStub().CreateCompositeKey(indexName, []string{marble.Color, marble.Name}) if err != nil { - return shim.Error(err.Error()) + return err } // Save index entry to state. Only the key name is needed, no need to store a duplicate copy of the marble. // Note - passing a 'nil' value will effectively delete the key from state, therefore we pass null character as value value := []byte{0x00} - stub.PutPrivateData("collectionMarbles", colorNameIndexKey, value) + err = ctx.GetStub().PutPrivateData("collectionMarbles", colorNameIndexKey, value) // ==== Marble saved and indexed. Return success ==== - fmt.Println("- end init marble") - return shim.Success(nil) + + return nil + } // =============================================== // readMarble - read a marble from chaincode state // =============================================== -func (t *SimpleChaincode) readMarble(stub shim.ChaincodeStubInterface, args []string) pb.Response { - var name, jsonResp string - var err error - if len(args) != 1 { - return shim.Error("Incorrect number of arguments. Expecting name of the marble to query") - } +func (s *SmartContract) ReadMarble(ctx contractapi.TransactionContextInterface, marbleID string) (*Marble, error) { - name = args[0] - valAsbytes, err := stub.GetPrivateData("collectionMarbles", name) //get the marble from chaincode state + marbleJSON, err := ctx.GetStub().GetPrivateData("collectionMarbles", marbleID) //get the marble from chaincode state if err != nil { - jsonResp = "{\"Error\":\"Failed to get state for " + name + ": " + err.Error() + "\"}" - return shim.Error(jsonResp) - } else if valAsbytes == nil { - jsonResp = "{\"Error\":\"Marble does not exist: " + name + "\"}" - return shim.Error(jsonResp) - } + return nil, fmt.Errorf("failed to read from marble %s", err.Error()) + } + if marbleJSON == nil { + return nil, fmt.Errorf("%s does not exist", marbleID) + } + + marble := new(Marble) + _ = json.Unmarshal(marbleJSON, marble) + + return marble, nil - return shim.Success(valAsbytes) } // =============================================== -// readMarblereadMarblePrivateDetails - read a marble private details from chaincode state +// ReadMarblePrivateDetails - read a marble private details from chaincode state // =============================================== -func (t *SimpleChaincode) readMarblePrivateDetails(stub shim.ChaincodeStubInterface, args []string) pb.Response { - var name, jsonResp string - var err error +func (s *SmartContract) ReadMarblePrivateDetails(ctx contractapi.TransactionContextInterface, marbleID string) (*MarblePrivateDetails, error) { - if len(args) != 1 { - return shim.Error("Incorrect number of arguments. Expecting name of the marble to query") - } + marbleDetailsJSON, err := ctx.GetStub().GetPrivateData("collectionMarblePrivateDetails", marbleID) //get the marble from chaincode state + if err != nil { + return nil, fmt.Errorf("failed to read from marble details %s", err.Error()) + } + if marbleDetailsJSON == nil { + return nil, fmt.Errorf("%s does not exist", marbleID) + } - name = args[0] - valAsbytes, err := stub.GetPrivateData("collectionMarblePrivateDetails", name) //get the marble private details from chaincode state - if err != nil { - jsonResp = "{\"Error\":\"Failed to get private details for " + name + ": " + err.Error() + "\"}" - return shim.Error(jsonResp) - } else if valAsbytes == nil { - jsonResp = "{\"Error\":\"Marble private details does not exist: " + name + "\"}" - return shim.Error(jsonResp) - } + marbleDetails := new(MarblePrivateDetails) + _ = json.Unmarshal(marbleDetailsJSON, marbleDetails) - return shim.Success(valAsbytes) + return marbleDetails, nil } // ================================================== // delete - remove a marble key/value pair from state // ================================================== -func (t *SimpleChaincode) delete(stub shim.ChaincodeStubInterface, args []string) pb.Response { - fmt.Println("- start delete marble") +func (s *SmartContract) Delete(ctx contractapi.TransactionContextInterface) error { - type marbleDeleteTransientInput struct { - Name string `json:"name"` - } + transMap, err := ctx.GetStub().GetTransient() + if err != nil { + return fmt.Errorf("Error getting transient: " + err.Error()) + } - if len(args) != 0 { - return shim.Error("Incorrect number of arguments. Private marble name must be passed in transient map.") - } + // Marble properties are private, therefore they get passed in transient field + transientDeleteMarbleJSON, ok := transMap["marble_delete"] + if !ok { + return fmt.Errorf("marble to delete not found in the transient map") + } - transMap, err := stub.GetTransient() - if err != nil { - return shim.Error("Error getting transient: " + err.Error()) - } + type marbleDelete struct { + Name string `json:"name"` + } - marbleDeleteJsonBytes, ok := transMap["marble_delete"] - if !ok { - return shim.Error("marble_delete must be a key in the transient map") - } - - if len(marbleDeleteJsonBytes) == 0 { - return shim.Error("marble_delete value in the transient map must be a non-empty JSON string") - } - - var marbleDeleteInput marbleDeleteTransientInput - err = json.Unmarshal(marbleDeleteJsonBytes, &marbleDeleteInput) - if err != nil { - return shim.Error("Failed to decode JSON of: " + string(marbleDeleteJsonBytes)) - } + var marbleDeleteInput marbleDelete + err = json.Unmarshal(transientDeleteMarbleJSON, &marbleDeleteInput) + if err != nil { + return fmt.Errorf("failed to unmarshal JSON: %s", err.Error()) + } if len(marbleDeleteInput.Name) == 0 { - return shim.Error("name field must be a non-empty string") + return fmt.Errorf("name field must be a non-empty string") } // to maintain the color~name index, we need to read the marble first and get its color - valAsbytes, err := stub.GetPrivateData("collectionMarbles", marbleDeleteInput.Name) //get the marble from chaincode state - if err != nil { - return shim.Error("Failed to get state for " + marbleDeleteInput.Name) - } else if valAsbytes == nil { - return shim.Error("Marble does not exist: " + marbleDeleteInput.Name) - } + valAsbytes, err := ctx.GetStub().GetPrivateData("collectionMarbles", marbleDeleteInput.Name) //get the marble from chaincode state + if err != nil { + return fmt.Errorf("failed to read marble: %s", err.Error()) + } + if valAsbytes == nil { + return fmt.Errorf("marble private details does not exist: %s", marbleDeleteInput.Name) + } - var marbleToDelete marble + var marbleToDelete Marble err = json.Unmarshal([]byte(valAsbytes), &marbleToDelete) if err != nil { - return shim.Error("Failed to decode JSON of: " + string(valAsbytes)) + return fmt.Errorf("failed to unmarshal JSON: %s", err.Error()) } // delete the marble from state - err = stub.DelPrivateData("collectionMarbles", marbleDeleteInput.Name) + err = ctx.GetStub().DelPrivateData("collectionMarbles", marbleDeleteInput.Name) if err != nil { - return shim.Error("Failed to delete state:" + err.Error()) + return fmt.Errorf("Failed to delete state:" + err.Error()) } // Also delete the marble from the color~name index indexName := "color~name" - colorNameIndexKey, err := stub.CreateCompositeKey(indexName, []string{marbleToDelete.Color, marbleToDelete.Name}) + colorNameIndexKey, err := ctx.GetStub().CreateCompositeKey(indexName, []string{marbleToDelete.Color, marbleToDelete.Name}) if err != nil { - return shim.Error(err.Error()) + return err } - err = stub.DelPrivateData("collectionMarbles", colorNameIndexKey) + err = ctx.GetStub().DelPrivateData("collectionMarbles", colorNameIndexKey) if err != nil { - return shim.Error("Failed to delete state:" + err.Error()) + return fmt.Errorf("Failed to delete marble:" + err.Error()) } // Finally, delete private details of marble - err = stub.DelPrivateData("collectionMarblePrivateDetails", marbleDeleteInput.Name) + err = ctx.GetStub().DelPrivateData("collectionMarblePrivateDetails", marbleDeleteInput.Name) if err != nil { - return shim.Error(err.Error()) + return err } - return shim.Success(nil) + return nil + } // =========================================================== // transfer a marble by setting a new owner name on the marble // =========================================================== -func (t *SimpleChaincode) transferMarble(stub shim.ChaincodeStubInterface, args []string) pb.Response { +func (s *SmartContract) TransferMarble(ctx contractapi.TransactionContextInterface) error { - fmt.Println("- start transfer marble") + transMap, err := ctx.GetStub().GetTransient() + if err != nil { + return fmt.Errorf("Error getting transient: " + err.Error()) + } + + // Marble properties are private, therefore they get passed in transient field + transientTransferMarbleJSON, ok := transMap["marble_owner"] + if !ok { + return fmt.Errorf("marble owner not found in the transient map") + } type marbleTransferTransientInput struct { Name string `json:"name"` Owner string `json:"owner"` } - if len(args) != 0 { - return shim.Error("Incorrect number of arguments. Private marble data must be passed in transient map.") - } - - transMap, err := stub.GetTransient() - if err != nil { - return shim.Error("Error getting transient: " + err.Error()) - } - - marbleOwnerJsonBytes, ok := transMap["marble_owner"] - if !ok { - return shim.Error("marble_owner must be a key in the transient map") - } - - if len(marbleOwnerJsonBytes) == 0 { - return shim.Error("marble_owner value in the transient map must be a non-empty JSON string") - } - var marbleTransferInput marbleTransferTransientInput - err = json.Unmarshal(marbleOwnerJsonBytes, &marbleTransferInput) + err = json.Unmarshal(transientTransferMarbleJSON, &marbleTransferInput) if err != nil { - return shim.Error("Failed to decode JSON of: " + string(marbleOwnerJsonBytes)) + return fmt.Errorf("failed to unmarshal JSON: %s", err.Error()) } + if len(marbleTransferInput.Name) == 0 { - return shim.Error("name field must be a non-empty string") + return fmt.Errorf("name field must be a non-empty string") } if len(marbleTransferInput.Owner) == 0 { - return shim.Error("owner field must be a non-empty string") + return fmt.Errorf("owner field must be a non-empty string") } - marbleAsBytes, err := stub.GetPrivateData("collectionMarbles", marbleTransferInput.Name) - if err != nil { - return shim.Error("Failed to get marble:" + err.Error()) - } else if marbleAsBytes == nil { - return shim.Error("Marble does not exist: " + marbleTransferInput.Name) - } + marbleAsBytes, err := ctx.GetStub().GetPrivateData("collectionMarbles", marbleTransferInput.Name) + if err != nil { + return fmt.Errorf("Failed to get marble:" + err.Error()) + } else if marbleAsBytes == nil { + return fmt.Errorf("Marble does not exist: " + marbleTransferInput.Name) + } - marbleToTransfer := marble{} + marbleToTransfer := Marble{} err = json.Unmarshal(marbleAsBytes, &marbleToTransfer) //unmarshal it aka JSON.parse() - if err != nil { - return shim.Error(err.Error()) - } + if err != nil { + return fmt.Errorf("failed to unmarshal JSON: %s", err.Error()) + } + marbleToTransfer.Owner = marbleTransferInput.Owner //change the owner marbleJSONasBytes, _ := json.Marshal(marbleToTransfer) - err = stub.PutPrivateData("collectionMarbles", marbleToTransfer.Name, marbleJSONasBytes) //rewrite the marble - if err != nil { - return shim.Error(err.Error()) - } + err = ctx.GetStub().PutPrivateData("collectionMarbles", marbleToTransfer.Name, marbleJSONasBytes) //rewrite the marble + if err != nil { + return err + } + + return nil - fmt.Println("- end transferMarble (success)") - return shim.Success(nil) } // =========================================================================================== @@ -503,51 +413,37 @@ func (t *SimpleChaincode) transferMarble(stub shim.ChaincodeStubInterface, args // time and commit time. // Therefore, range queries are a safe option for performing update transactions based on query results. // =========================================================================================== -func (t *SimpleChaincode) getMarblesByRange(stub shim.ChaincodeStubInterface, args []string) pb.Response { +func (s *SmartContract) GetMarblesByRange(ctx contractapi.TransactionContextInterface, startKey string, endKey string) ([]Marble, error) { - if len(args) < 2 { - return shim.Error("Incorrect number of arguments. Expecting 2") - } - - startKey := args[0] - endKey := args[1] - - resultsIterator, err := stub.GetPrivateDataByRange("collectionMarbles", startKey, endKey) + resultsIterator, err := ctx.GetStub().GetPrivateDataByRange("collectionMarbles", startKey, endKey) if err != nil { - return shim.Error(err.Error()) + return nil, err } defer resultsIterator.Close() - // buffer is a JSON array containing QueryResults - var buffer bytes.Buffer - buffer.WriteString("[") + results := []Marble{} - bArrayMemberAlreadyWritten := false for resultsIterator.HasNext() { - queryResponse, err := resultsIterator.Next() + response, 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 { - buffer.WriteString(",") + return nil, err } - buffer.WriteString( - fmt.Sprintf( - `{"Key":"%s", "Record":%s}`, - queryResponse.Key, queryResponse.Value, - ), - ) - bArrayMemberAlreadyWritten = true + newMarble := new(Marble) + + err = json.Unmarshal(response.Value, newMarble) + if err != nil { + return nil, err + } + + results = append(results, *newMarble) } - buffer.WriteString("]") - fmt.Printf("- getMarblesByRange queryResult:\n%s\n", buffer.String()) + return results, nil - return shim.Success(buffer.Bytes()) } + // =======Rich queries ========================================================================= // Two examples of rich queries are provided below (parameterized query and ad hoc query). // Rich queries pass a query string to the state database. @@ -567,23 +463,17 @@ func (t *SimpleChaincode) getMarblesByRange(stub shim.ChaincodeStubInterface, ar // and accepting a single query parameter (owner). // Only available on state databases that support rich query (e.g. CouchDB) // ========================================================================================= -func (t *SimpleChaincode) queryMarblesByOwner(stub shim.ChaincodeStubInterface, args []string) pb.Response { +func (s *SmartContract) QueryMarblesByOwner(ctx contractapi.TransactionContextInterface, owner string) ([]Marble, error) { - // 0 - // "bob" - if len(args) < 1 { - return shim.Error("Incorrect number of arguments. Expecting 1") - } + ownerString := strings.ToLower(owner) - owner := strings.ToLower(args[0]) + queryString := fmt.Sprintf("{\"selector\":{\"docType\":\"marble\",\"owner\":\"%s\"}}", ownerString) - queryString := fmt.Sprintf("{\"selector\":{\"docType\":\"marble\",\"owner\":\"%s\"}}", owner) - - queryResults, err := getQueryResultForQueryString(stub, queryString) + queryResults, err := s.getQueryResultForQueryString(ctx, queryString) if err != nil { - return shim.Error(err.Error()) + return nil, err } - return shim.Success(queryResults) + return queryResults, nil } // ===== Example: Ad hoc rich query ======================================================== @@ -593,91 +483,74 @@ func (t *SimpleChaincode) queryMarblesByOwner(stub shim.ChaincodeStubInterface, // If this is not desired, follow the queryMarblesForOwner example for parameterized queries. // Only available on state databases that support rich query (e.g. CouchDB) // ========================================================================================= -func (t *SimpleChaincode) queryMarbles(stub shim.ChaincodeStubInterface, args []string) pb.Response { +func (s *SmartContract) QueryMarbles(ctx contractapi.TransactionContextInterface, queryString string) ([]Marble, error) { - // 0 - // "queryString" - if len(args) < 1 { - return shim.Error("Incorrect number of arguments. Expecting 1") - } - - queryString := args[0] - - queryResults, err := getQueryResultForQueryString(stub, queryString) + queryResults, err := s.getQueryResultForQueryString(ctx, queryString) if err != nil { - return shim.Error(err.Error()) + return nil, err } - return shim.Success(queryResults) + return queryResults, nil } // ========================================================================================= // getQueryResultForQueryString executes the passed in query string. // Result set is built and returned as a byte array containing the JSON results. // ========================================================================================= -func getQueryResultForQueryString(stub shim.ChaincodeStubInterface, queryString string) ([]byte, error) { +func (s *SmartContract) getQueryResultForQueryString(ctx contractapi.TransactionContextInterface, queryString string) ([]Marble, error) { - fmt.Printf("- getQueryResultForQueryString queryString:\n%s\n", queryString) - - resultsIterator, err := stub.GetPrivateDataQueryResult("collectionMarbles", queryString) + resultsIterator, err := ctx.GetStub().GetPrivateDataQueryResult("collectionMarbles", queryString) if err != nil { return nil, err } defer resultsIterator.Close() - // buffer is a JSON array containing QueryRecords - var buffer bytes.Buffer - buffer.WriteString("[") + results := []Marble{} - bArrayMemberAlreadyWritten := false for resultsIterator.HasNext() { - queryResponse, err := resultsIterator.Next() + response, 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(",") + + newMarble := new(Marble) + + err = json.Unmarshal(response.Value, newMarble) + if err != nil { + return nil, err } - 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 + results = append(results, *newMarble) } - buffer.WriteString("]") - - fmt.Printf("- getQueryResultForQueryString queryResult:\n%s\n", buffer.String()) - - return buffer.Bytes(), nil + return results, nil } // =============================================== // getMarbleHash - use the public data hash to verify a private marble // Result is the hash on the public ledger of a marble stored a private data collection // =============================================== -func (t *SimpleChaincode) getMarbleHash(stub shim.ChaincodeStubInterface, args []string) pb.Response { - var name, collection string - var err error - - if len(args) != 2 { - return shim.Error("Incorrect number of arguments. Expecting the collection and the name of the marble to query") - } - - collection = args[0] - name = args[1] +func (s *SmartContract) GetMarbleHash(ctx contractapi.TransactionContextInterface, collection string, marbleID string,) (string, error) { // GetPrivateDataHash can use any collection deployed with the chaincode as input - hashAsbytes, err := stub.GetPrivateDataHash(collection, name) + hashAsbytes, err := ctx.GetStub().GetPrivateDataHash(collection, marbleID) if err != nil { - return shim.Error("Failed to get public data hash for marble:" + err.Error()) + return "", fmt.Errorf("Failed to get public data hash for marble:" + err.Error()) } else if hashAsbytes == nil { - return shim.Error("Marble does not exist: " + name) + return "", fmt.Errorf("Marble does not exist: " + marbleID) } - return shim.Success(hashAsbytes) + return string(hashAsbytes), nil +} + +func main() { + + chaincode, err := contractapi.NewChaincode(new(SmartContract)) + + if err != nil { + fmt.Printf("Error creating private mables chaincode: %s", err.Error()) + return + } + + if err := chaincode.Start(); err != nil { + fmt.Printf("Error starting private mables chaincode: %s", err.Error()) + } }