func (rs *Contract) RegisterCCKeys(ctx contractapi.TransactionContextInterface, ccKeyRegistrationMessageBase64 string) error {
	return fmt.Errorf("not implemented yet")
}
RegisterCCKeys  registers a CCKeyRegistration message that confirms that an enclave is provisioned with the chaincode encryption key.
This method is used during the key generation and key distribution protocol. In particular, during key generation,
this call sets the chaincode_ek for a chaincode if no chaincode_ek is set yet.
package registry
import (
	"encoding/base64"
	"fmt"
	"github.com/hyperledger/fabric-contract-api-go/contractapi"
	"github.com/hyperledger/fabric-private-chaincode/ercc/attestation"
	"github.com/hyperledger/fabric-private-chaincode/internal/protos"
	"github.com/hyperledger/fabric-private-chaincode/internal/utils"
	"github.com/hyperledger/fabric/common/flogging"
	"github.com/pkg/errors"
)
var logger = flogging.MustGetLogger("ercc")
type Contract struct {
	contractapi.Contract
	Verifier   attestation.VerifierInterface
	IEvaluator utils.IdentityEvaluatorInterface
}
func MyBeforeTransaction(ctx contractapi.TransactionContextInterface) error {
	function, _ := ctx.GetStub().GetFunctionAndParameters()
	logger.Debugf("Invoke [%s]", function)
	return nil
}
func (rs *Contract) QueryListEnclaveCredentials(ctx contractapi.TransactionContextInterface, chaincodeId string) ([]string, error) {
	iter, err := ctx.GetStub().GetStateByPartialCompositeKey("namespaces/credentials", []string{chaincodeId})
	if iter != nil {
		defer iter.Close()
	}
	if err != nil {
		return nil, err
	}
	if iter == nil {
		return nil, nil
	}
	var allCredentials []string
	for iter.HasNext() {
		q, err := iter.Next()
		if err != nil {
			return nil, err
		}
		credentialsBase64 := string(q.Value)
		allCredentials = append(allCredentials, credentialsBase64)
	}
	return allCredentials, nil
}
func (rs *Contract) QueryEnclaveCredentials(ctx contractapi.TransactionContextInterface, chaincodeId string, enclaveId string) (string, error) {
	key, err := ctx.GetStub().CreateCompositeKey("namespaces/credentials", []string{chaincodeId, enclaveId})
	if err != nil {
		return "", err
	}
	credentialsBase64, err := ctx.GetStub().GetState(key)
	if err != nil {
		return "", err
	}
	return string(credentialsBase64), nil
}
func (rs *Contract) QueryListProvisionedEnclaves(ctx contractapi.TransactionContextInterface, chaincodeId string) ([]string, error) {
	iter, err := ctx.GetStub().GetStateByPartialCompositeKey("namespaces/credentials", []string{chaincodeId})
	if err != nil {
		return nil, err
	}
	defer func() {
		cerr := iter.Close()
		if err == nil {
			err = cerr
		}
	}()
	var enclaveIds []string
	for iter.HasNext() {
		q, err := iter.Next()
		if err != nil {
			return nil, err
		}
		_, res, err := ctx.GetStub().SplitCompositeKey(q.Key)
		if err != nil {
			return nil, err
		}
		enclaveId := res[1]
		k, err := ctx.GetStub().CreateCompositeKey("namespaces/provisioned", []string{chaincodeId, enclaveId})
		if err != nil {
			return nil, err
		}
		p, err := ctx.GetStub().GetState(k)
		if err != nil {
			return nil, err
		}
		if p != nil {
			enclaveIds = append(enclaveIds, enclaveId)
		}
	}
	return enclaveIds, err
}
func (rs *Contract) QueryChaincodeEndPoints(ctx contractapi.TransactionContextInterface, chaincodeId string) (string, error) {
	iter, err := ctx.GetStub().GetStateByPartialCompositeKey("namespaces/credentials", []string{chaincodeId})
	if iter != nil {
		defer iter.Close()
	}
	if err != nil {
		return "", err
	}
	if iter == nil {
		return "", nil
	}
	peerEndpoints := ""
	for iter.HasNext() {
		q, err := iter.Next()
		if err != nil {
			return "", err
		}
		credentialsBase64 := string(q.Value)
		credentials, err := utils.UnmarshalCredentials(credentialsBase64)
		if err != nil {
			return "", err
		}
		endpoint, err := utils.ExtractEndpoint(credentials)
		if err != nil {
			return "", err
		}
		if peerEndpoints != "" {
			peerEndpoints = peerEndpoints + "," + endpoint
		} else {
			peerEndpoints = endpoint
		}
	}
	return peerEndpoints, nil
}
func (rs *Contract) QueryChaincodeEncryptionKey(ctx contractapi.TransactionContextInterface, chaincodeId string) (string, error) {
	iter, err := ctx.GetStub().GetStateByPartialCompositeKey("namespaces/credentials", []string{chaincodeId})
	if iter != nil {
		defer iter.Close()
	}
	if err != nil {
		return "", err
	}
	q, err := iter.Next()
	if err != nil {
		return "", err
	}
	_, res, err := ctx.GetStub().SplitCompositeKey(q.Key)
	if err != nil {
		logger.Debugf("no split")
		return "", err
	}
	enclaveId := res[1]
	k, err := ctx.GetStub().CreateCompositeKey("namespaces/credentials", []string{chaincodeId, enclaveId})
	if err != nil {
		return "", err
	}
	credentialsBase64, err := ctx.GetStub().GetState(k)
	if err != nil {
		return "", err
	}
	credentials, err := utils.UnmarshalCredentials(string(credentialsBase64))
	if err != nil {
		return "", err
	}
	var attestedData protos.AttestedData
	if err := credentials.SerializedAttestedData.UnmarshalTo(&attestedData); err != nil {
		return "", err
	}
	chaincodeEKBytes := attestedData.GetChaincodeEk()
	b64ChaincodeEK := base64.StdEncoding.EncodeToString(chaincodeEKBytes)
	logger.Debugf("QueryChaincodeEncryptionKey: EK: '%s' / EK b64: '%s'", string(chaincodeEKBytes), b64ChaincodeEK)
	return b64ChaincodeEK, nil
}
func (rs *Contract) RegisterEnclave(ctx contractapi.TransactionContextInterface, credentialsBase64 string) error {
	logger.Debugf("RegisterEnclave")
	credentials, err := utils.UnmarshalCredentials(credentialsBase64)
	if err != nil {
		return errors.Wrap(err, "invalid credential bytes")
	}
	if len(credentials.Evidence) == 0 {
		return errors.New("evidence is empty")
	}
	attestedData, err := utils.UnmarshalAttestedData(credentials.SerializedAttestedData)
	if err != nil {
		return errors.Wrap(err, "invalid attested data message")
	}
	logger.Debugf("- verifying attested data (%s) against evidence (%s)", attestedData.String(), string(credentials.Evidence))
	if err := checkAttestedData(ctx, rs.Verifier, rs.IEvaluator, attestedData, credentials); err != nil {
		return err
	}
	chaincodeId := attestedData.CcParams.ChaincodeId
	enclaveId := utils.GetEnclaveId(attestedData)
	key, err := ctx.GetStub().CreateCompositeKey("namespaces/credentials", []string{chaincodeId, enclaveId})
	if err != nil {
		return err
	}
	registeredCredentialsList, _ := rs.QueryListEnclaveCredentials(ctx, chaincodeId)
	if registeredCredentialsList != nil {
		return fmt.Errorf("an enclave is already registered for chaincode %s", chaincodeId)
	}
	logger.Debugf("Registering credentials at key %s", key)
	if err := ctx.GetStub().PutState(key, []byte(credentialsBase64)); err != nil {
		return fmt.Errorf("cannot store credentials: %s", err)
	}
	provisionedKey, err := ctx.GetStub().CreateCompositeKey("namespaces/provisioned", []string{chaincodeId, enclaveId})
	if err != nil {
		return fmt.Errorf("cannot create provisionedKey: %s", err)
	}
	if err := ctx.GetStub().PutState(provisionedKey, []byte("a SignedCCKeyRegistrationMessage")); err != nil {
		return fmt.Errorf("cannot store provisionedKey: %s", err)
	}
	logger.Debugf("RegisterEnclave successful")
	return nil
}
func checkAttestedData(ctx contractapi.TransactionContextInterface, v attestation.VerifierInterface, ie utils.IdentityEvaluatorInterface, attestedData *protos.AttestedData, credentials *protos.Credentials) error {
	if attestedData.CcParams.ChannelId != ctx.GetStub().GetChannelID() {
		return fmt.Errorf("wrong channel! expected=%s, actual=%s", ctx.GetStub().GetChannelID(), attestedData.CcParams.ChannelId)
	}
	ccDef, err := utils.GetChaincodeDefinition(attestedData.CcParams.ChaincodeId, ctx.GetStub())
	if err != nil {
		return fmt.Errorf("cannot get chaincode definition: %s", err)
	}
	expectedMrEnclave := ccDef.Version
	if attestedData.CcParams.Version != expectedMrEnclave {
		return fmt.Errorf("mrenclave does not match chaincode definition")
	}
	if attestedData.CcParams.Sequence != ccDef.Sequence {
		return fmt.Errorf("sequence does not match chaincode definition")
	}
	if err := v.VerifyEvidence(credentials.Evidence, credentials.SerializedAttestedData.Value, expectedMrEnclave); err != nil {
		return fmt.Errorf("evidence verification failed: %s", err)
	}
	if attestedData.HostParams == nil {
		return errors.New("host params are empty")
	}
	creatorIdentityBytes, err := ctx.GetStub().GetCreator()
	if err != nil {
		return err
	}
	if err := ie.EvaluateCreatorIdentity(creatorIdentityBytes, attestedData.HostParams.PeerMspId); err != nil {
		return fmt.Errorf("creator identity evaluation failed: %s", err)
	}
	return nil
}