3

I have chaincode with the following directory structure

$GOPATH/myproject/chaincode/mycc/go
├── mycc.go
├── chaincode
│   └── chaincode.go
└── vendor
    ├── github.com
    ├── ...

Because of my usage of hyperledgers cid package, I use vendoring and have the vendor directory next to the chaincode. Now for testablitiy, mycc.go only includes the main function:

package main

import (
    "myproject/chaincode/mycc/go/chaincode"
    "github.com/hyperledger/fabric/core/chaincode/shim"
)

func main() {
    err := shim.Start(new(chaincode.MyChaincode))
    if err != nil {
        logger.Error(err.Error())
    }
}

The chaincode.go implements the rest of the chaincode, including the MyChaincode struct with Init, Invoke, etc. The relevant imports are identical to the one in the mycc.go:

"github.com/hyperledger/fabric/core/chaincode/shim"

During the instantiation of the chaincode, something with the dependencies seems to be mixed up, because I receive the error message:

*chaincode.MyChaincode does not implement "chaincode/mycc/go/vendor/github.com/hyperledger/fabric/core/chaincode/shim".Chaincode (wrong type for Init method)
    have Init("chaincode/mycc/go/vendor/myproject/chaincode/mycc/go/vendor/github.com/hyperledger/fabric/core/chaincode/shim".ChaincodeStubInterface) "chaincode/approvalcc/go/vendor/ma/chaincode/approvalcc/go/vendor/github.com/hyperledger/fabric/protos/peer".Response
    want Init("chaincode/mycc/go/vendor/github.com/hyperledger/fabric/core/chaincode/shim".ChaincodeStubInterface) "chaincode/mycc/go/vendor/github.com/hyperledger/fabric/protos/peer".Response

So clearly it seems that the import in the inner chaincode package is resolved wrongly with the vendor directory appearing twice in the path.

Roper
  • 903
  • 1
  • 9
  • 17
  • 1
    Did you use the `peer chaincode package ...` and/or `peer chaincode install ...` commands? – Gari Singh Jul 07 '19 at 10:19
  • I'm using `peer chaincode install`. It is worth to note that there is no issue when I put all the code of the chaincode inside the main package. I just split it up for testability. – Roper Jul 07 '19 at 10:35
  • 1
    Ok ... the peer cli tries to be helpful when it packages stuff ... but see my answer below about moving the `vendor` folder to the top-level of the project. – Gari Singh Jul 07 '19 at 10:42

2 Answers2

1

It seems like your init method is not initialized properly so please check if the chaincode is installed or instantiated properly or not. That you can check out just by looking out for the instantiated chaincode docker container.

Trinayan
  • 867
  • 6
  • 15
  • The instantiation fails, but only for the chaincode that uses vendoring. Is this a vendoring problem? The issue is clearly that the sub package's import of the shim is resolved differently than the one in the main package. For some reason the `vendor` directory appears twice in the full import path of the shim in the sub package. – Roper Jul 07 '19 at 10:09
  • I am not sure about vendor directory but the correct path of the chaincode matters a lot while chaincode install command is executed as it will look out for some exact path for installation. – Trinayan Jul 07 '19 at 10:46
  • Everything works fine when I put all my chaincode functions into the `mycc.go` in the main package. Its just a problem with the sub package which I'd really like to keep. – Roper Jul 07 '19 at 11:15
1

The fabric-ccenv container which builds chaincode attempts to be "helpful" but including shim in the GOPATH inside the container. It also ends up including the shim/ext/... folders as well but unfortunately does not actually properly include their transitive dependencies.

When you combine this with how the chaincode install/package commands also attempt to be helpful and your attempt to vendor, things got ugly.

I actually just pushed a fix targeted for 1.4.2 to address the fabric-ccenv issue.

Gari Singh
  • 11,418
  • 2
  • 18
  • 41
  • The `mycc.go` contains the `shim.Start(...)` and is on the directory (`$GOPATH/myproject/chaincode/mycc/go`) which is installed using `peer chaincode install`. The `vendor` directory is currently on the same level than this main package. Moving it up higher right under `myproject` causes the instantiation to fail because then the main package uses `github.com/hyperledger/fabric/core/chaincode/shim` and the sub package refers to `chaincode/mycc/go/vendor/myproject/vendor/github.com/hyperledger/fabric/core/chaincode/shim` (same error, concering Init(), just a different import conflict) – Roper Jul 07 '19 at 11:12
  • 1
    Sorry ... I thought the `vendor` folder was under the `chaincode` directory. What tool are you using to vendor your dependencies? – Gari Singh Jul 08 '19 at 10:11
  • `govendor` as described here https://hyperledger-fabric.readthedocs.io/en/release-1.4/chaincode4ade.html#managing-external-dependencies-for-chaincode-written-in-go – Roper Jul 08 '19 at 19:49
  • 1
    Did you also vendor `github.com/hyperledger/fabric/core/chaincode/shim`? – Gari Singh Jul 09 '19 at 09:40
  • I used `govendor add +external` to all packages after experiencing some issues with only adding the `.../shim/cid` which is the reason for using vendoring in the first place. Now your suggestion made me be more selective and only add the packages transitively needed by `cid`. This seems to have resolved the error, as I am able to leave out the `shim` package from the vendor directory entirely. Thanks a lot for your help here. For others to note, when vendoring for the `.../shim/cid`, only `github.com/golang/protobuf` and `github.com/pkg/errors` are also needed to be vendored. – Roper Jul 09 '19 at 19:08