mirror of
https://github.com/hyperledger/fabric-samples.git
synced 2026-06-17 07:25:10 +00:00
[FAB-4371] - Chaincode Dev Mode
Adds a docker environment for running peer in dev mode pre-baked crypto and orderer/channel artifacts README still needs an updated curl command to bundle these scripts. simplified some of the paths add sacc from write your first chaincode remove binary Change-Id: Ic1537987c819f0350ae6dbf740fd00e1571045e5 Signed-off-by: Nick Gaski <ngaski@us.ibm.com> Signed-off-by: Christopher Ferris <chrisfer@us.ibm.com>
This commit is contained in:
parent
ec254d983c
commit
ba777f3bcb
14 changed files with 724 additions and 0 deletions
3
.gitignore
vendored
3
.gitignore
vendored
|
|
@ -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
|
||||
|
|
|
|||
140
chaincode-docker-devmode/README.rst
Normal file
140
chaincode-docker-devmode/README.rst
Normal file
|
|
@ -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/
|
||||
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
@ -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")
|
||||
}
|
||||
97
chaincode-docker-devmode/chaincode/sacc/sacc.go
Normal file
97
chaincode-docker-devmode/chaincode/sacc/sacc.go
Normal file
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
87
chaincode-docker-devmode/docker-compose-simple.yaml
Normal file
87
chaincode-docker-devmode/docker-compose-simple.yaml
Normal file
|
|
@ -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
|
||||
16
chaincode-docker-devmode/msp/admincerts/admincert.pem
Normal file
16
chaincode-docker-devmode/msp/admincerts/admincert.pem
Normal file
|
|
@ -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-----
|
||||
15
chaincode-docker-devmode/msp/cacerts/cacert.pem
Normal file
15
chaincode-docker-devmode/msp/cacerts/cacert.pem
Normal file
|
|
@ -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-----
|
||||
8
chaincode-docker-devmode/msp/config.yaml
Normal file
8
chaincode-docker-devmode/msp/config.yaml
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
# Copyright IBM Corp. All Rights Reserved.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
|
||||
OrganizationalUnitIdentifiers:
|
||||
- Certificate: "cacerts/cacert.pem"
|
||||
OrganizationalUnitIdentifier: "COP"
|
||||
5
chaincode-docker-devmode/msp/keystore/key.pem
Normal file
5
chaincode-docker-devmode/msp/keystore/key.pem
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
-----BEGIN EC PRIVATE KEY-----
|
||||
MHcCAQEEIAsWwFunEzqz1Rh6nvD4MiPkKCtmoxzh3jTquG5MSbeLoAoGCCqGSM49
|
||||
AwEHoUQDQgAEHBuKsAO43hs4JGpFfiGMkB/xsILTsOvmN2WmwpsPHZNL6w8HWe3x
|
||||
CPQtdG/XJJvZ+C756KEsUBM3yw5PTfku8g==
|
||||
-----END EC PRIVATE KEY-----
|
||||
16
chaincode-docker-devmode/msp/signcerts/peer.pem
Normal file
16
chaincode-docker-devmode/msp/signcerts/peer.pem
Normal file
|
|
@ -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-----
|
||||
BIN
chaincode-docker-devmode/myc.tx
Normal file
BIN
chaincode-docker-devmode/myc.tx
Normal file
Binary file not shown.
BIN
chaincode-docker-devmode/orderer.block
Normal file
BIN
chaincode-docker-devmode/orderer.block
Normal file
Binary file not shown.
26
chaincode-docker-devmode/script.sh
Executable file
26
chaincode-docker-devmode/script.sh
Executable file
|
|
@ -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
|
||||
Loading…
Reference in a new issue