I've set up a Fabric network, created a peer, and deployed a chaincode on a channel all via the CLI following the instructions. From there I was able to invoke a transaction on the blockchain, so far so good.
However, when I tried to connect up an existing golang service to the same blockchain, transactions are failing with this error:
CreateAndSendTransaction failed: SendTransaction failed: calling orderer 'nd-llr4vdvrmfbtxgpjvsqxwgplhy.m-23xnnp73k5ck7ik7cysya6oxdu.n-er3uwfzwnngjnmc2royh3zkukq.managedblockchain.eu-west-2.amazonaws.com:30001' failed: Orderer Client Status Code: (2) CONNECTION_FAILED. Description: dialing connection on target [nd-llr4vdvrmfbtxgpjvsqxwgplhy.m-23xnnp73k5ck7ik7cysya6oxdu.n-er3uwfzwnngjnmc2royh3zkukq.managedblockchain.eu-west-2.amazonaws.com:30001]: waiting for connection failed: context deadline exceeded
I've created a minimal test application that I'm running within the same VM as we're accessing the cli from to take away any possible networking issues and any other complexities in our main service, and it's giving us the same issue. My feeling is that it's related to certificates, but I've double and triple checked all the config and can't see anything wrong. Here's the test app code:
package main
import (
"encoding/json"
"log"
"github.com/hyperledger/fabric-sdk-go/pkg/client/channel"
"github.com/hyperledger/fabric-sdk-go/pkg/client/resmgmt"
"github.com/hyperledger/fabric-sdk-go/pkg/common/providers/fab"
"github.com/hyperledger/fabric-sdk-go/pkg/core/config"
"github.com/hyperledger/fabric-sdk-go/pkg/fabsdk"
)
type Client struct {
// Fabric network information
ConfigPath string
OrgName string
OrgAdmin string
OrgUser string
// sdk clients
SDK *fabsdk.FabricSDK
rc *resmgmt.Client
cc *channel.Client
// Same for each peer
ChannelID string
CCID string // chaincode ID, eq name
CCPath string // chaincode source path
CCGoPath string // GOPATH used for chaincode
}
func New(cfg, org, admin, user string) *Client {
c := &Client{
ConfigPath: cfg,
OrgName: org,
OrgAdmin: admin,
OrgUser: user,
CCID: "diamonds",
ChannelID: "diamonds-staging",
}
// create sdk
sdk, err := fabsdk.New(config.FromFile(c.ConfigPath))
if err != nil {
log.Panicf("failed to create fabric sdk: %s", err)
}
c.SDK = sdk
log.Println("Initialized fabric sdk")
c.rc, c.cc = NewSdkClient(sdk, c.ChannelID, c.OrgName, c.OrgAdmin, c.OrgUser)
return c
}
// NewSdkClient create resource client and channel client
func NewSdkClient(sdk *fabsdk.FabricSDK, channelID, orgName, orgAdmin, OrgUser string) (rc *resmgmt.Client, cc *channel.Client) {
var err error
// create rc
rcp := sdk.Context(fabsdk.WithUser(orgAdmin), fabsdk.WithOrg(orgName))
rc, err = resmgmt.New(rcp)
if err != nil {
log.Panicf("failed to create resource client: %s", err)
}
log.Println("Initialized resource client")
// create cc
ccp := sdk.ChannelContext(channelID, fabsdk.WithUser(OrgUser))
cc, err = channel.New(ccp)
if err != nil {
log.Panicf("failed to create channel client: %s", err)
}
log.Println("Initialized channel client")
return rc, cc
}
// RegisterChaincodeEvent more easy than event client to registering chaincode event.
func (c *Client) RegisterChaincodeEvent(ccid, eventName string) (fab.Registration, <-chan *fab.CCEvent, error) {
return c.cc.RegisterChaincodeEvent(ccid, eventName)
}
func getArrayDataAsBytes(arr []interface{}) (*[][]byte, error) {
var args [][]byte
for _, data := range arr {
switch v := data.(type) {
case string:
args = append(args, []byte(v))
default:
b, err := json.Marshal(data)
if err != nil {
}
args = append(args, b)
}
}
return &args, nil
}
func main() {
c := New("./config/amb.fabric.yml", "m-ZWBHVVBYQZEPDGKZPGAFNRU6PY", "evledgeramb", "evledgeramb")
print(c)
req := []interface{}{`{
<payload json removed>}
`}
args, err := getArrayDataAsBytes(req)
if err != nil {
log.Println(err)
}
res, err := c.cc.Execute(channel.Request{ChaincodeID: "diamonds", Fcn: "EventOriginRegisterInvoice", Args: *args})
if err != nil {
log.Println(err)
}
log.Println(res)
}
and here is the config read in from ./config/amb.fabric.json:
---
name: amb-network
description: The connection profile of AMB instance
version: 1.0.0
client:
tlsEnable: true
organization: m-ZWBHVVBYQZEPDGKZPGAFNRU6PY
logging:
level: info
peer:
timeout:
endorser: 6000
eventHub: 6000
eventReg: 6000
orderer:
timeout:
connection: 6000
response: 120s
BCCSP:
security:
enabled: false
default:
provider: SW
hashAlgorithm: SHA2
softVerify: true
ephemeral: false
level: 256
tlsCerts:
systemCertPool: false
channels:
diamonds-uat:
peers:
nd-twx2gf7f75btjmx7g6vpj2d5u4.m-zwbhvvbyqzepdgkzpgafnru6py.n-er3uwfzwnngjnmc2royh3zkukq.managedblockchain.eu-west-2.amazonaws.com:
endorsingPeer: true
chaincodeQuery: true
ledgerQuery: true
eventSource: true
diamonds-staging:
peers:
nd-twx2gf7f75btjmx7g6vpj2d5u4.m-zwbhvvbyqzepdgkzpgafnru6py.n-er3uwfzwnngjnmc2royh3zkukq.managedblockchain.eu-west-2.amazonaws.com:
endorsingPeer: true
chaincodeQuery: true
ledgerQuery: true
eventSource: true
diamonds-production:
peers:
nd-twx2gf7f75btjmx7g6vpj2d5u4.m-zwbhvvbyqzepdgkzpgafnru6py.n-er3uwfzwnngjnmc2royh3zkukq.managedblockchain.eu-west-2.amazonaws.com:
endorsingPeer: true
chaincodeQuery: true
ledgerQuery: true
eventSource: true
organizations:
m-ZWBHVVBYQZEPDGKZPGAFNRU6PY:
mspid: m-ZWBHVVBYQZEPDGKZPGAFNRU6PY
peers:
- nd-twx2gf7f75btjmx7g6vpj2d5u4.m-zwbhvvbyqzepdgkzpgafnru6py.n-er3uwfzwnngjnmc2royh3zkukq.managedblockchain.eu-west-2.amazonaws.com
cryptoPath: users/evledgeramb
users:
evledgeramb:
cert:
path: /home/ec2-user/admin-msp/admincerts/cert.pem
key:
path: /home/ec2-user/admin-msp/keystore/389e36f6ee143a371bf2c1b5775eced1080cf4bf94ad3f3128691be2ae7e90dc_sk
certificateAuthorities:
- ca-org1
peers:
nd-twx2gf7f75btjmx7g6vpj2d5u4.m-zwbhvvbyqzepdgkzpgafnru6py.n-er3uwfzwnngjnmc2royh3zkukq.managedblockchain.eu-west-2.amazonaws.com:
tlsCACerts:
path: /home/ec2-user/managedblockchain-tls-chain.pem
url: grpcs://nd-twx2gf7f75btjmx7g6vpj2d5u4.m-zwbhvvbyqzepdgkzpgafnru6py.n-er3uwfzwnngjnmc2royh3zkukq.managedblockchain.eu-west-2.amazonaws.com:30003
eventUrl: grpcs://nd-twx2gf7f75btjmx7g6vpj2d5u4.m-zwbhvvbyqzepdgkzpgafnru6py.n-er3uwfzwnngjnmc2royh3zkukq.managedblockchain.eu-west-2.amazonaws.com:30004
grpcOptions:
ssl-target-name-override: nd-twx2gf7f75btjmx7g6vpj2d5u4.m-zwbhvvbyqzepdgkzpgafnru6py.n-er3uwfzwnngjnmc2royh3zkukq.managedblockchain.eu-west-2.amazonaws.com
discovery-as-localhost: false
orderers:
orderer:
tlsCACerts:
path: /home/ec2-user/managedblockchain-tls-chain.pem
url: grpcs://orderer.n-er3uwfzwnngjnmc2royh3zkukq.managedblockchain.eu-west-2.amazonaws.com:30001
grpcOptions:
ssl-target-name-override: orderer.n-er3uwfzwnngjnmc2royh3zkukq.managedblockchain.eu-west-2.amazonaws.com
grpc-max-send-message-length: -1
keep-alive-time: 360s
keep-alive-timeout: 360s
certificateAuthorities:
ca-org1:
url: https://ca.m-zwbhvvbyqzepdgkzpgafnru6py.n-er3uwfzwnngjnmc2royh3zkukq.managedblockchain.eu-west-2.amazonaws.com:30002
httpOptions:
verify: false
tlsCACerts:
path: /home/ec2-user/managedblockchain-tls-chain.pem
caName: m-ZWBHVVBYQZEPDGKZPGAFNRU6PY
I've imported the keys and certs by path here, one for privacy and also to ensure that we are using the same contents as when we invoke the transaction from the CLI. Here is the command I've been using to invoke the same transaction via the cli, which does succeed using the same TLS cert:
docker exec cli peer chaincode invoke --tls --cafile /opt/home/managedblockchain-tls-chain.pem --channelID diamonds-staging --name diamonds -c '{"Args":["EventOriginRegisterInvoice","{<payload json removed>}"]}'
Any suggestions or advice gratefully received, this has been driving me crazy for a couple of days now!