diff --git a/.gitignore b/.gitignore index d7f10ff6e1..863125a999 100644 --- a/.gitignore +++ b/.gitignore @@ -11,3 +11,6 @@ first-network/channel-artifacts/*.tx first-network/channel-artifacts/*.block first-network/crypto-config/* +chaincode-docker-devmode/myc.block +chaincode-docker-devmode/chaincode/sacc/sacc +chaincode-docker-devmode/chaincode/chaincode_example02/chaincode_example02 diff --git a/chaincode-docker-devmode/README.rst b/chaincode-docker-devmode/README.rst new file mode 100644 index 0000000000..b9f64dd139 --- /dev/null +++ b/chaincode-docker-devmode/README.rst @@ -0,0 +1,140 @@ +Using dev mode +============== + +Normally chaincodes are started and maintained by peer. However in “dev +mode", chaincode is built and started by the user. This mode is useful +during chaincode development phase for rapid code/build/run/debug cycle +turnaround. + +We start "dev mode" by leveraging pre-generated orderer and channel artifacts for +a sample dev network. As such, the user can immediately jump into the process +of compiling chaincode and driving calls. + +Install Fabric Samples +---------------------- + +If you haven't already done so, please install the :doc:`samples`. + +Navigate to the ``chaincode-docker-devmode`` directory of the ``fabric-samples`` +clone: + +.. code:: bash + + cd chaincode-docker-devmode + +Download docker images +^^^^^^^^^^^^^^^^^^^^^^ + +We need four docker images in order for "dev mode" to run against the supplied +docker compose script. If you installed the ``fabric-samples`` repo clone and +followed the instructions to :ref:`download-platform-specific-binaries`, then +you should have the necessary Docker images installed locally. + +.. note:: If you choose to manually pull the images then you must retag them as + ``latest``. + +Issue a ``docker images`` command to reveal your local Docker Registry. You +should see something similar to following: + +.. code:: bash + + docker images + REPOSITORY TAG IMAGE ID CREATED SIZE + hyperledger/fabric-tools latest e09f38f8928d 4 hours ago 1.32 GB + hyperledger/fabric-tools x86_64-1.0.0-rc1-snapshot-f20846c6 e09f38f8928d 4 hours ago 1.32 GB + hyperledger/fabric-orderer latest 0df93ba35a25 4 hours ago 179 MB + hyperledger/fabric-orderer x86_64-1.0.0-rc1-snapshot-f20846c6 0df93ba35a25 4 hours ago 179 MB + hyperledger/fabric-peer latest 533aec3f5a01 4 hours ago 182 MB + hyperledger/fabric-peer x86_64-1.0.0-rc1-snapshot-f20846c6 533aec3f5a01 4 hours ago 182 MB + hyperledger/fabric-ccenv latest 4b70698a71d3 4 hours ago 1.29 GB + hyperledger/fabric-ccenv x86_64-1.0.0-rc1-snapshot-f20846c6 4b70698a71d3 4 hours ago 1.29 GB + +.. note:: If you retrieved the images through the :ref:`download-platform-specific-binaries`, + then you will see additional images listed. However, we are only concerned with + these four. + +Now open three terminals and navigate to your ``chaincode-docker-devmode`` +directory in each. + +Terminal 1 - Start the network +------------------------------ + +.. code:: bash + + docker-compose -f docker-compose-simple.yaml up + +The above starts the network with the ``SingleSampleMSPSolo`` orderer profile and +launches the peer in "dev mode". It also launches two additional containers - +one for the chaincode environment and a CLI to interact with the chaincode. The +commands for create and join channel are embedded in the CLI container, so we +can jump immediately to the chaincode calls. + +Terminal 2 - Build & start the chaincode +---------------------------------------- + +.. code:: bash + + docker exec -it chaincode bash + +You should see the following: + +.. code:: bash + + root@d2629980e76b:/opt/gopath/src/chaincode# + +Now, compile your chaincode: + +.. code:: bash + + cd chaincode_example02 + go build + +Now run the chaincode: + +.. code:: bash + + CORE_PEER_ADDRESS=peer:7051 CORE_CHAINCODE_ID_NAME=mycc:0 ./chaincode_example02 + +The chaincode is started with peer and chaincode logs indicating successful registration with the peer. +Note that at this stage the chaincode is not associated with any channel. This is done in subsequent steps +using the ``instantiate`` command. + +Terminal 3 - Use the chaincode +------------------------------ + +Even though you are in ``--peer-chaincodedev`` mode, you still have to install the +chaincode so the life-cycle system chaincode can go through its checks normally. +This requirement may be removed in future when in ``--peer-chaincodedev`` mode. + +We'll leverage the CLI container to drive these calls. + +.. code:: bash + + docker exec -it cli bash + +.. code:: bash + + peer chaincode install -p chaincodedev/chaincode/chaincode_example02 -n mycc -v 0 + peer chaincode instantiate -n mycc -v 0 -c '{"Args":["init","a","100","b","200"]}' -C myc + +Now issue an invoke to move ``10`` from ``a`` to ``b``. + +.. code:: bash + + peer chaincode invoke -n mycc -c '{"Args":["invoke","a","b","10"]}' -C myc + +Finally, query ``a``. We should see a value of ``90``. + +.. code:: bash + + peer chaincode query -n mycc -c '{"Args":["query","a"]}' -C myc + +Testing new chaincode +--------------------- + +By default, we mount only ``chaincode_example02``. However, you can easily test different +chaincodes by adding them to the ``chaincode`` subdirectory and relaunching +your network. At this point they will be accessible in your ``chaincode`` container. + +.. Licensed under Creative Commons Attribution 4.0 International License + https://creativecommons.org/licenses/by/4.0/ diff --git a/chaincode-docker-devmode/chaincode/chaincode_example02/chaincode_example02.go b/chaincode-docker-devmode/chaincode/chaincode_example02/chaincode_example02.go new file mode 100644 index 0000000000..5343806643 --- /dev/null +++ b/chaincode-docker-devmode/chaincode/chaincode_example02/chaincode_example02.go @@ -0,0 +1,199 @@ +/* +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. +*/ + +package main + +//WARNING - this chaincode's ID is hard-coded in chaincode_example04 to illustrate one way of +//calling chaincode from a chaincode. If this example is modified, chaincode_example04.go has +//to be modified as well with the new ID of chaincode_example02. +//chaincode_example05 show's how chaincode ID can be passed in as a parameter instead of +//hard-coding. + +import ( + "fmt" + "strconv" + + "github.com/hyperledger/fabric/core/chaincode/shim" + pb "github.com/hyperledger/fabric/protos/peer" +) + +// SimpleChaincode example simple Chaincode implementation +type SimpleChaincode struct { +} + +func (t *SimpleChaincode) Init(stub shim.ChaincodeStubInterface) pb.Response { + fmt.Println("ex02 Init") + _, args := stub.GetFunctionAndParameters() + var A, B string // Entities + var Aval, Bval int // Asset holdings + var err error + + if len(args) != 4 { + return shim.Error("Incorrect number of arguments. Expecting 4") + } + + // Initialize the chaincode + A = args[0] + Aval, err = strconv.Atoi(args[1]) + if err != nil { + return shim.Error("Expecting integer value for asset holding") + } + B = args[2] + Bval, err = strconv.Atoi(args[3]) + if err != nil { + return shim.Error("Expecting integer value for asset holding") + } + fmt.Printf("Aval = %d, Bval = %d\n", Aval, Bval) + + // Write the state to the ledger + err = stub.PutState(A, []byte(strconv.Itoa(Aval))) + if err != nil { + return shim.Error(err.Error()) + } + + err = stub.PutState(B, []byte(strconv.Itoa(Bval))) + if err != nil { + return shim.Error(err.Error()) + } + + return shim.Success(nil) +} + +func (t *SimpleChaincode) Invoke(stub shim.ChaincodeStubInterface) pb.Response { + fmt.Println("ex02 Invoke") + function, args := stub.GetFunctionAndParameters() + if function == "invoke" { + // Make payment of X units from A to B + return t.invoke(stub, args) + } else if function == "delete" { + // Deletes an entity from its state + return t.delete(stub, args) + } else if function == "query" { + // the old "Query" is now implemtned in invoke + return t.query(stub, args) + } + + return shim.Error("Invalid invoke function name. Expecting \"invoke\" \"delete\" \"query\"") +} + +// Transaction makes payment of X units from A to B +func (t *SimpleChaincode) invoke(stub shim.ChaincodeStubInterface, args []string) pb.Response { + var A, B string // Entities + var Aval, Bval int // Asset holdings + var X int // Transaction value + var err error + + if len(args) != 3 { + return shim.Error("Incorrect number of arguments. Expecting 3") + } + + A = args[0] + B = args[1] + + // Get the state from the ledger + // TODO: will be nice to have a GetAllState call to ledger + Avalbytes, err := stub.GetState(A) + if err != nil { + return shim.Error("Failed to get state") + } + if Avalbytes == nil { + return shim.Error("Entity not found") + } + Aval, _ = strconv.Atoi(string(Avalbytes)) + + Bvalbytes, err := stub.GetState(B) + if err != nil { + return shim.Error("Failed to get state") + } + if Bvalbytes == nil { + return shim.Error("Entity not found") + } + Bval, _ = strconv.Atoi(string(Bvalbytes)) + + // Perform the execution + X, err = strconv.Atoi(args[2]) + if err != nil { + return shim.Error("Invalid transaction amount, expecting a integer value") + } + Aval = Aval - X + Bval = Bval + X + fmt.Printf("Aval = %d, Bval = %d\n", Aval, Bval) + + // Write the state back to the ledger + err = stub.PutState(A, []byte(strconv.Itoa(Aval))) + if err != nil { + return shim.Error(err.Error()) + } + + err = stub.PutState(B, []byte(strconv.Itoa(Bval))) + if err != nil { + return shim.Error(err.Error()) + } + + return shim.Success(nil) +} + +// Deletes an entity from state +func (t *SimpleChaincode) delete(stub shim.ChaincodeStubInterface, args []string) pb.Response { + if len(args) != 1 { + return shim.Error("Incorrect number of arguments. Expecting 1") + } + + A := args[0] + + // Delete the key from the state in ledger + err := stub.DelState(A) + if err != nil { + return shim.Error("Failed to delete state") + } + + return shim.Success(nil) +} + +// query callback representing the query of a chaincode +func (t *SimpleChaincode) query(stub shim.ChaincodeStubInterface, args []string) pb.Response { + var A string // Entities + var err error + + if len(args) != 1 { + return shim.Error("Incorrect number of arguments. Expecting name of the person to query") + } + + A = args[0] + + // Get the state from the ledger + Avalbytes, err := stub.GetState(A) + if err != nil { + jsonResp := "{\"Error\":\"Failed to get state for " + A + "\"}" + return shim.Error(jsonResp) + } + + if Avalbytes == nil { + jsonResp := "{\"Error\":\"Nil amount for " + A + "\"}" + return shim.Error(jsonResp) + } + + jsonResp := "{\"Name\":\"" + A + "\",\"Amount\":\"" + string(Avalbytes) + "\"}" + fmt.Printf("Query Response:%s\n", jsonResp) + return shim.Success(Avalbytes) +} + +func main() { + err := shim.Start(new(SimpleChaincode)) + if err != nil { + fmt.Printf("Error starting Simple chaincode: %s", err) + } +} diff --git a/chaincode-docker-devmode/chaincode/chaincode_example02/chaincode_example02_test.go b/chaincode-docker-devmode/chaincode/chaincode_example02/chaincode_example02_test.go new file mode 100644 index 0000000000..c6c8ed7f34 --- /dev/null +++ b/chaincode-docker-devmode/chaincode/chaincode_example02/chaincode_example02_test.go @@ -0,0 +1,112 @@ +/* +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. +*/ +package main + +import ( + "fmt" + "testing" + + "github.com/hyperledger/fabric/core/chaincode/shim" +) + +func checkInit(t *testing.T, stub *shim.MockStub, args [][]byte) { + res := stub.MockInit("1", args) + if res.Status != shim.OK { + fmt.Println("Init failed", string(res.Message)) + t.FailNow() + } +} + +func checkState(t *testing.T, stub *shim.MockStub, name string, value string) { + bytes := stub.State[name] + if bytes == nil { + fmt.Println("State", name, "failed to get value") + t.FailNow() + } + if string(bytes) != value { + fmt.Println("State value", name, "was not", value, "as expected") + t.FailNow() + } +} + +func checkQuery(t *testing.T, stub *shim.MockStub, name string, value string) { + res := stub.MockInvoke("1", [][]byte{[]byte("query"), []byte(name)}) + if res.Status != shim.OK { + fmt.Println("Query", name, "failed", string(res.Message)) + t.FailNow() + } + if res.Payload == nil { + fmt.Println("Query", name, "failed to get value") + t.FailNow() + } + if string(res.Payload) != value { + fmt.Println("Query value", name, "was not", value, "as expected") + t.FailNow() + } +} + +func checkInvoke(t *testing.T, stub *shim.MockStub, args [][]byte) { + res := stub.MockInvoke("1", args) + if res.Status != shim.OK { + fmt.Println("Invoke", args, "failed", string(res.Message)) + t.FailNow() + } +} + +func TestExample02_Init(t *testing.T) { + scc := new(SimpleChaincode) + stub := shim.NewMockStub("ex02", scc) + + // Init A=123 B=234 + checkInit(t, stub, [][]byte{[]byte("init"), []byte("A"), []byte("123"), []byte("B"), []byte("234")}) + + checkState(t, stub, "A", "123") + checkState(t, stub, "B", "234") +} + +func TestExample02_Query(t *testing.T) { + scc := new(SimpleChaincode) + stub := shim.NewMockStub("ex02", scc) + + // Init A=345 B=456 + checkInit(t, stub, [][]byte{[]byte("init"), []byte("A"), []byte("345"), []byte("B"), []byte("456")}) + + // Query A + checkQuery(t, stub, "A", "345") + + // Query B + checkQuery(t, stub, "B", "456") +} + +func TestExample02_Invoke(t *testing.T) { + scc := new(SimpleChaincode) + stub := shim.NewMockStub("ex02", scc) + + // Init A=567 B=678 + checkInit(t, stub, [][]byte{[]byte("init"), []byte("A"), []byte("567"), []byte("B"), []byte("678")}) + + // Invoke A->B for 123 + checkInvoke(t, stub, [][]byte{[]byte("invoke"), []byte("A"), []byte("B"), []byte("123")}) + checkQuery(t, stub, "A", "444") + checkQuery(t, stub, "B", "801") + + // Invoke B->A for 234 + checkInvoke(t, stub, [][]byte{[]byte("invoke"), []byte("B"), []byte("A"), []byte("234")}) + checkQuery(t, stub, "A", "678") + checkQuery(t, stub, "B", "567") + checkQuery(t, stub, "A", "678") + checkQuery(t, stub, "B", "567") +} diff --git a/chaincode-docker-devmode/chaincode/sacc/sacc.go b/chaincode-docker-devmode/chaincode/sacc/sacc.go new file mode 100644 index 0000000000..4bfb165b5b --- /dev/null +++ b/chaincode-docker-devmode/chaincode/sacc/sacc.go @@ -0,0 +1,97 @@ +/* + * Copyright IBM Corp All Rights Reserved + * + * SPDX-License-Identifier: Apache-2.0 + */ + +package main + +import ( + "fmt" + + "github.com/hyperledger/fabric/core/chaincode/shim" + "github.com/hyperledger/fabric/protos/peer" +) + +// SimpleAsset implements a simple chaincode to manage an asset +type SimpleAsset struct { +} + +// Init is called during chaincode instantiation to initialize any +// data. Note that chaincode upgrade also calls this function to reset +// or to migrate data. +func (t *SimpleAsset) Init(stub shim.ChaincodeStubInterface) peer.Response { + // Get the args from the transaction proposal + args := stub.GetStringArgs() + if len(args) != 2 { + return shim.Error("Incorrect arguments. Expecting a key and a value") + } + + // Set up any variables or assets here by calling stub.PutState() + + // We store the key and the value on the ledger + err := stub.PutState(args[0], []byte(args[1])) + if err != nil { + return shim.Error(fmt.Sprintf("Failed to create asset: %s", args[0])) + } + return shim.Success(nil) +} + +// Invoke is called per transaction on the chaincode. Each transaction is +// either a 'get' or a 'set' on the asset created by Init function. The Set +// method may create a new asset by specifying a new key-value pair. +func (t *SimpleAsset) Invoke(stub shim.ChaincodeStubInterface) peer.Response { + // Extract the function and args from the transaction proposal + fn, args := stub.GetFunctionAndParameters() + + var result string + var err error + if fn == "set" { + result, err = set(stub, args) + } else { // assume 'get' even if fn is nil + result, err = get(stub, args) + } + if err != nil { + return shim.Error(err.Error()) + } + + // Return the result as success payload + return shim.Success([]byte(result)) +} + +// Set stores the asset (both key and value) on the ledger. If the key exists, +// it will override the value with the new one +func set(stub shim.ChaincodeStubInterface, args []string) (string, error) { + if len(args) != 2 { + return "", fmt.Errorf("Incorrect arguments. Expecting a key and a value") + } + + err := stub.PutState(args[0], []byte(args[1])) + if err != nil { + return "", fmt.Errorf("Failed to set asset: %s", args[0]) + } + return args[1], nil +} + +// Get returns the value of the specified asset key +func get(stub shim.ChaincodeStubInterface, args []string) (string, error) { + if len(args) != 1 { + return "", fmt.Errorf("Incorrect arguments. Expecting a key") + } + + value, err := stub.GetState(args[0]) + if err != nil { + return "", fmt.Errorf("Failed to get asset: %s with error: %s", args[0], err) + } + if value == nil { + return "", fmt.Errorf("Asset not found: %s", args[0]) + } + return string(value), nil +} + +// main function starts up the chaincode in the container during instantiate +func main() { + if err := shim.Start(new(SimpleAsset)); err != nil { + fmt.Printf("Error starting SimpleAsset chaincode: %s", err) + } +} diff --git a/chaincode-docker-devmode/docker-compose-simple.yaml b/chaincode-docker-devmode/docker-compose-simple.yaml new file mode 100644 index 0000000000..9803708011 --- /dev/null +++ b/chaincode-docker-devmode/docker-compose-simple.yaml @@ -0,0 +1,87 @@ +version: '2' + +services: + orderer: + container_name: orderer + image: hyperledger/fabric-orderer + environment: + - ORDERER_GENERAL_LOGLEVEL=debug + - ORDERER_GENERAL_LISTENADDRESS=orderer + - ORDERER_GENERAL_GENESISMETHOD=file + - ORDERER_GENERAL_GENESISFILE=orderer.block + - ORDERER_GENERAL_LOCALMSPID=DEFAULT + - ORDERER_GENERAL_LOCALMSPDIR=/etc/hyperledger/msp + - GRPC_TRACE=all=true, + - GRPC_VERBOSITY=debug + working_dir: /opt/gopath/src/github.com/hyperledger/fabric + command: orderer + volumes: + - ./msp:/etc/hyperledger/msp + - ./orderer.block:/etc/hyperledger/fabric/orderer.block + ports: + - 7050:7050 + peer: + container_name: peer + image: hyperledger/fabric-peer + environment: + - CORE_PEER_ID=peer + - CORE_PEER_ADDRESS=peer:7051 + - CORE_PEER_GOSSIP_EXTERNALENDPOINT=peer:7051 + - CORE_PEER_LOCALMSPID=DEFAULT + - CORE_VM_ENDPOINT=unix:///host/var/run/docker.sock + - CORE_LOGGING_LEVEL=DEBUG + - CORE_PEER_MSPCONFIGPATH=/etc/hyperledger/msp + volumes: + - /var/run/:/host/var/run/ + - ./msp:/etc/hyperledger/msp + working_dir: /opt/gopath/src/github.com/hyperledger/fabric/peer + command: peer node start --peer-chaincodedev=true -o orderer:7050 + ports: + - 7051:7051 + - 7053:7053 + depends_on: + - orderer + + cli: + container_name: cli + image: hyperledger/fabric-tools + tty: true + environment: + - GOPATH=/opt/gopath + - CORE_VM_ENDPOINT=unix:///host/var/run/docker.sock + - CORE_LOGGING_LEVEL=DEBUG + - CORE_PEER_ID=cli + - CORE_PEER_ADDRESS=peer:7051 + - CORE_PEER_LOCALMSPID=DEFAULT + - CORE_PEER_MSPCONFIGPATH=/etc/hyperledger/msp + working_dir: /opt/gopath/src/chaincodedev + command: /bin/bash -c './script.sh' + volumes: + - /var/run/:/host/var/run/ + - ./msp:/etc/hyperledger/msp + - ./:/opt/gopath/src/chaincodedev + depends_on: + - orderer + - peer + + chaincode: + container_name: chaincode + image: hyperledger/fabric-ccenv + tty: true + environment: + - GOPATH=/opt/gopath + - CORE_VM_ENDPOINT=unix:///host/var/run/docker.sock + - CORE_LOGGING_LEVEL=DEBUG + - CORE_PEER_ID=example02 + - CORE_PEER_ADDRESS=peer:7051 + - CORE_PEER_LOCALMSPID=DEFAULT + - CORE_PEER_MSPCONFIGPATH=/etc/hyperledger/msp + working_dir: /opt/gopath/src/chaincode + command: /bin/bash -c 'sleep 6000000' + volumes: + - /var/run/:/host/var/run/ + - ./msp:/etc/hyperledger/msp + - ./chaincode:/opt/gopath/src/chaincode + depends_on: + - orderer + - peer diff --git a/chaincode-docker-devmode/msp/admincerts/admincert.pem b/chaincode-docker-devmode/msp/admincerts/admincert.pem new file mode 100644 index 0000000000..5f6293ac39 --- /dev/null +++ b/chaincode-docker-devmode/msp/admincerts/admincert.pem @@ -0,0 +1,16 @@ +-----BEGIN CERTIFICATE----- +MIICjDCCAjKgAwIBAgIUBEVwsSx0TmqdbzNwleNBBzoIT0wwCgYIKoZIzj0EAwIw +fzELMAkGA1UEBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExFjAUBgNVBAcTDVNh +biBGcmFuY2lzY28xHzAdBgNVBAoTFkludGVybmV0IFdpZGdldHMsIEluYy4xDDAK +BgNVBAsTA1dXVzEUMBIGA1UEAxMLZXhhbXBsZS5jb20wHhcNMTYxMTExMTcwNzAw +WhcNMTcxMTExMTcwNzAwWjBjMQswCQYDVQQGEwJVUzEXMBUGA1UECBMOTm9ydGgg +Q2Fyb2xpbmExEDAOBgNVBAcTB1JhbGVpZ2gxGzAZBgNVBAoTEkh5cGVybGVkZ2Vy +IEZhYnJpYzEMMAoGA1UECxMDQ09QMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE +HBuKsAO43hs4JGpFfiGMkB/xsILTsOvmN2WmwpsPHZNL6w8HWe3xCPQtdG/XJJvZ ++C756KEsUBM3yw5PTfku8qOBpzCBpDAOBgNVHQ8BAf8EBAMCBaAwHQYDVR0lBBYw +FAYIKwYBBQUHAwEGCCsGAQUFBwMCMAwGA1UdEwEB/wQCMAAwHQYDVR0OBBYEFOFC +dcUZ4es3ltiCgAVDoyLfVpPIMB8GA1UdIwQYMBaAFBdnQj2qnoI/xMUdn1vDmdG1 +nEgQMCUGA1UdEQQeMByCCm15aG9zdC5jb22CDnd3dy5teWhvc3QuY29tMAoGCCqG +SM49BAMCA0gAMEUCIDf9Hbl4xn3z4EwNKmilM9lX2Fq4jWpAaRVB97OmVEeyAiEA +25aDPQHGGq2AvhKT0wvt08cX1GTGCIbfmuLpMwKQj38= +-----END CERTIFICATE----- diff --git a/chaincode-docker-devmode/msp/cacerts/cacert.pem b/chaincode-docker-devmode/msp/cacerts/cacert.pem new file mode 100644 index 0000000000..8d98dfa59e --- /dev/null +++ b/chaincode-docker-devmode/msp/cacerts/cacert.pem @@ -0,0 +1,15 @@ +-----BEGIN CERTIFICATE----- +MIICYjCCAgmgAwIBAgIUB3CTDOU47sUC5K4kn/Caqnh114YwCgYIKoZIzj0EAwIw +fzELMAkGA1UEBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExFjAUBgNVBAcTDVNh +biBGcmFuY2lzY28xHzAdBgNVBAoTFkludGVybmV0IFdpZGdldHMsIEluYy4xDDAK +BgNVBAsTA1dXVzEUMBIGA1UEAxMLZXhhbXBsZS5jb20wHhcNMTYxMDEyMTkzMTAw +WhcNMjExMDExMTkzMTAwWjB/MQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZv +cm5pYTEWMBQGA1UEBxMNU2FuIEZyYW5jaXNjbzEfMB0GA1UEChMWSW50ZXJuZXQg +V2lkZ2V0cywgSW5jLjEMMAoGA1UECxMDV1dXMRQwEgYDVQQDEwtleGFtcGxlLmNv +bTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABKIH5b2JaSmqiQXHyqC+cmknICcF +i5AddVjsQizDV6uZ4v6s+PWiJyzfA/rTtMvYAPq/yeEHpBUB1j053mxnpMujYzBh +MA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBQXZ0I9 +qp6CP8TFHZ9bw5nRtZxIEDAfBgNVHSMEGDAWgBQXZ0I9qp6CP8TFHZ9bw5nRtZxI +EDAKBggqhkjOPQQDAgNHADBEAiAHp5Rbp9Em1G/UmKn8WsCbqDfWecVbZPQj3RK4 +oG5kQQIgQAe4OOKYhJdh3f7URaKfGTf492/nmRmtK+ySKjpHSrU= +-----END CERTIFICATE----- diff --git a/chaincode-docker-devmode/msp/config.yaml b/chaincode-docker-devmode/msp/config.yaml new file mode 100644 index 0000000000..63bec1e0d0 --- /dev/null +++ b/chaincode-docker-devmode/msp/config.yaml @@ -0,0 +1,8 @@ +# Copyright IBM Corp. All Rights Reserved. +# +# SPDX-License-Identifier: Apache-2.0 +# + +OrganizationalUnitIdentifiers: + - Certificate: "cacerts/cacert.pem" + OrganizationalUnitIdentifier: "COP" diff --git a/chaincode-docker-devmode/msp/keystore/key.pem b/chaincode-docker-devmode/msp/keystore/key.pem new file mode 100644 index 0000000000..ba48df9180 --- /dev/null +++ b/chaincode-docker-devmode/msp/keystore/key.pem @@ -0,0 +1,5 @@ +-----BEGIN EC PRIVATE KEY----- +MHcCAQEEIAsWwFunEzqz1Rh6nvD4MiPkKCtmoxzh3jTquG5MSbeLoAoGCCqGSM49 +AwEHoUQDQgAEHBuKsAO43hs4JGpFfiGMkB/xsILTsOvmN2WmwpsPHZNL6w8HWe3x +CPQtdG/XJJvZ+C756KEsUBM3yw5PTfku8g== +-----END EC PRIVATE KEY----- diff --git a/chaincode-docker-devmode/msp/signcerts/peer.pem b/chaincode-docker-devmode/msp/signcerts/peer.pem new file mode 100644 index 0000000000..5f6293ac39 --- /dev/null +++ b/chaincode-docker-devmode/msp/signcerts/peer.pem @@ -0,0 +1,16 @@ +-----BEGIN CERTIFICATE----- +MIICjDCCAjKgAwIBAgIUBEVwsSx0TmqdbzNwleNBBzoIT0wwCgYIKoZIzj0EAwIw +fzELMAkGA1UEBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExFjAUBgNVBAcTDVNh +biBGcmFuY2lzY28xHzAdBgNVBAoTFkludGVybmV0IFdpZGdldHMsIEluYy4xDDAK +BgNVBAsTA1dXVzEUMBIGA1UEAxMLZXhhbXBsZS5jb20wHhcNMTYxMTExMTcwNzAw +WhcNMTcxMTExMTcwNzAwWjBjMQswCQYDVQQGEwJVUzEXMBUGA1UECBMOTm9ydGgg +Q2Fyb2xpbmExEDAOBgNVBAcTB1JhbGVpZ2gxGzAZBgNVBAoTEkh5cGVybGVkZ2Vy +IEZhYnJpYzEMMAoGA1UECxMDQ09QMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE +HBuKsAO43hs4JGpFfiGMkB/xsILTsOvmN2WmwpsPHZNL6w8HWe3xCPQtdG/XJJvZ ++C756KEsUBM3yw5PTfku8qOBpzCBpDAOBgNVHQ8BAf8EBAMCBaAwHQYDVR0lBBYw +FAYIKwYBBQUHAwEGCCsGAQUFBwMCMAwGA1UdEwEB/wQCMAAwHQYDVR0OBBYEFOFC +dcUZ4es3ltiCgAVDoyLfVpPIMB8GA1UdIwQYMBaAFBdnQj2qnoI/xMUdn1vDmdG1 +nEgQMCUGA1UdEQQeMByCCm15aG9zdC5jb22CDnd3dy5teWhvc3QuY29tMAoGCCqG +SM49BAMCA0gAMEUCIDf9Hbl4xn3z4EwNKmilM9lX2Fq4jWpAaRVB97OmVEeyAiEA +25aDPQHGGq2AvhKT0wvt08cX1GTGCIbfmuLpMwKQj38= +-----END CERTIFICATE----- diff --git a/chaincode-docker-devmode/myc.tx b/chaincode-docker-devmode/myc.tx new file mode 100644 index 0000000000..f6eabee83d Binary files /dev/null and b/chaincode-docker-devmode/myc.tx differ diff --git a/chaincode-docker-devmode/orderer.block b/chaincode-docker-devmode/orderer.block new file mode 100644 index 0000000000..1546cfdb65 Binary files /dev/null and b/chaincode-docker-devmode/orderer.block differ diff --git a/chaincode-docker-devmode/script.sh b/chaincode-docker-devmode/script.sh new file mode 100755 index 0000000000..e910c423f6 --- /dev/null +++ b/chaincode-docker-devmode/script.sh @@ -0,0 +1,26 @@ +#!/bin/bash +# Copyright London Stock Exchange Group All Rights Reserved. +# +# SPDX-License-Identifier: Apache-2.0 +set -e +# This script expedites the chaincode development process by automating the +# requisite channel create/join commands + +# We use a pre-generated orderer.block and channel transaction artifact (myc.tx), +# both of which are created using the configtxgen tool + +# first we create the channel against the specified configuration in myc.tx +# this call returns a channel configuration block - myc.block - to the CLI container +peer channel create -c myc -f myc.tx -o orderer:7050 + +# now we will join the channel and start the chain with myc.block serving as the +# channel's first block (i.e. the genesis block) +peer channel join -b myc.block + +# Now the user can proceed to build and start chaincode in one terminal +# And leverage the CLI container to issue install instantiate invoke query commands in another + +#we should have bailed if above commands failed. +#we are here, so they worked +sleep 600000 +exit 0