go_study/fabric-main/integration/e2e/instantiation_policy_test.go

358 lines
10 KiB
Go

/*
Copyright IBM Corp All Rights Reserved.
SPDX-License-Identifier: Apache-2.0
*/
package e2e
import (
"crypto/sha256"
"encoding/hex"
"io/ioutil"
"os"
"syscall"
"time"
docker "github.com/fsouza/go-dockerclient"
"github.com/golang/protobuf/proto"
"github.com/golang/protobuf/ptypes"
"github.com/hyperledger/fabric-protos-go/common"
"github.com/hyperledger/fabric-protos-go/ledger/rwset"
"github.com/hyperledger/fabric-protos-go/ledger/rwset/kvrwset"
"github.com/hyperledger/fabric-protos-go/peer"
"github.com/hyperledger/fabric/common/policydsl"
"github.com/hyperledger/fabric/integration/channelparticipation"
"github.com/hyperledger/fabric/integration/nwo"
"github.com/hyperledger/fabric/integration/nwo/commands"
"github.com/hyperledger/fabric/integration/ordererclient"
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
"github.com/onsi/gomega/gbytes"
"github.com/onsi/gomega/gexec"
"github.com/tedsuo/ifrit"
ginkgomon "github.com/tedsuo/ifrit/ginkgomon_v2"
)
var _ = Describe("InstantiationPolicy", func() {
var (
testDir string
client *docker.Client
network *nwo.Network
ordererRunner *ginkgomon.Runner
ordererProcess, peerProcess ifrit.Process
)
BeforeEach(func() {
var err error
testDir, err = ioutil.TempDir("", "e2e")
Expect(err).NotTo(HaveOccurred())
client, err = docker.NewClientFromEnv()
Expect(err).NotTo(HaveOccurred())
})
AfterEach(func() {
if ordererProcess != nil {
ordererProcess.Signal(syscall.SIGTERM)
Eventually(ordererProcess.Wait(), network.EventuallyTimeout).Should(Receive())
}
if peerProcess != nil {
peerProcess.Signal(syscall.SIGTERM)
Eventually(peerProcess.Wait(), network.EventuallyTimeout).Should(Receive())
}
if network != nil {
network.Cleanup()
}
os.RemoveAll(testDir)
})
Describe("single node etcdraft network with single peer", func() {
BeforeEach(func() {
config := nwo.MinimalRaft()
config.Profiles[0].Organizations = []string{"Org1", "Org2"}
network = nwo.New(config, testDir, client, StartPort(), components)
network.GenerateConfigTree()
network.Bootstrap()
// Start all the fabric processes
ordererRunner, ordererProcess, peerProcess = network.StartSingleOrdererNetwork("orderer")
})
It("honors the instantiation policy", func() {
orderer := network.Orderer("orderer")
org1Peer := network.Peer("Org1", "peer0")
org2Peer := network.Peer("Org2", "peer0")
channelparticipation.JoinOrdererJoinPeersAppChannel(network, "testchannel", orderer, ordererRunner)
By("attempting to deploy with an unsatisfied instantiation policy")
goodDeploy := LSCCOperation{
Operation: "deploy",
ChannelID: "testchannel",
Name: "fakecc",
Version: "badip",
InstantiationOrgs: []*nwo.Organization{
network.Organization("Org2"),
},
}
ordererclient.Broadcast(network, orderer, goodDeploy.Tx(network.PeerUserSigner(org1Peer, "Admin")))
nwo.WaitUntilEqualLedgerHeight(network, "testchannel", 2, org1Peer)
Expect(ListInstantiatedLegacy(network, org1Peer, "testchannel")).NotTo(gbytes.Say("Name: fakecc, Version: badip"))
By("attempting to deploy with a satisfied instantiation policy")
badDeploy := LSCCOperation{
Operation: "deploy",
ChannelID: "testchannel",
Name: "fakecc",
Version: "goodip",
InstantiationOrgs: []*nwo.Organization{
network.Organization("Org1"),
},
}
ordererclient.Broadcast(network, orderer, badDeploy.Tx(network.PeerUserSigner(org1Peer, "Admin")))
nwo.WaitUntilEqualLedgerHeight(network, "testchannel", 3, org1Peer)
Expect(ListInstantiatedLegacy(network, org1Peer, "testchannel")).To(gbytes.Say("Name: fakecc, Version: goodip"))
By("upgrading without satisfying the previous instantiation policy")
badUpgrade := LSCCOperation{
Operation: "upgrade",
ChannelID: "testchannel",
Name: "fakecc",
Version: "wrongsubmitter",
InstantiationOrgs: []*nwo.Organization{
network.Organization("Org2"),
},
}
ordererclient.Broadcast(network, orderer, badUpgrade.Tx(network.PeerUserSigner(org2Peer, "Admin")))
nwo.WaitUntilEqualLedgerHeight(network, "testchannel", 4, org1Peer)
Expect(ListInstantiatedLegacy(network, org1Peer, "testchannel")).NotTo(gbytes.Say("Name: fakecc, Version: wrongsubmitter"))
By("upgrading while satisfying the previous instantiation policy")
goodUpgrade := LSCCOperation{
Operation: "upgrade",
ChannelID: "testchannel",
Name: "fakecc",
Version: "rightsubmitter",
InstantiationOrgs: []*nwo.Organization{
network.Organization("Org1"),
},
}
ordererclient.Broadcast(network, orderer, goodUpgrade.Tx(network.PeerUserSigner(org1Peer, "Admin")))
nwo.WaitUntilEqualLedgerHeight(network, "testchannel", 5, org1Peer)
Expect(ListInstantiatedLegacy(network, org1Peer, "testchannel")).To(gbytes.Say("Name: fakecc, Version: rightsubmitter"))
})
})
})
func ListInstantiatedLegacy(n *nwo.Network, p *nwo.Peer, channel string) *gbytes.Buffer {
sess, err := n.PeerAdminSession(p, commands.ChaincodeListInstantiatedLegacy{
ChannelID: channel,
ClientAuth: n.ClientAuthRequired,
})
Expect(err).NotTo(HaveOccurred())
Eventually(sess, n.EventuallyTimeout).Should(gexec.Exit(0))
return sess.Buffer()
}
type LSCCOperation struct {
Operation string
ChannelID string
Name string
Version string
InstantiationOrgs []*nwo.Organization
}
func (lo *LSCCOperation) Tx(signer *nwo.SigningIdentity) *common.Envelope {
creatorBytes, err := signer.Serialize()
Expect(err).NotTo(HaveOccurred())
var instantiationMSPIDs []string
for _, org := range lo.InstantiationOrgs {
instantiationMSPIDs = append(instantiationMSPIDs, org.MSPID)
}
instantiationPolicy := policydsl.SignedByAnyMember(instantiationMSPIDs)
nonce, err := time.Now().MarshalBinary()
Expect(err).NotTo(HaveOccurred())
timestamp, err := ptypes.TimestampProto(time.Now().UTC())
Expect(err).NotTo(HaveOccurred())
hasher := sha256.New()
hasher.Write(nonce)
hasher.Write(creatorBytes)
txid := hex.EncodeToString(hasher.Sum(nil))
signatureHeaderBytes := protoMarshal(&common.SignatureHeader{
Creator: creatorBytes,
Nonce: nonce,
})
channelHeaderBytes := protoMarshal(&common.ChannelHeader{
ChannelId: lo.ChannelID,
Extension: protoMarshal(&peer.ChaincodeHeaderExtension{
ChaincodeId: &peer.ChaincodeID{
Name: "lscc",
},
}),
Timestamp: timestamp,
TxId: txid,
Type: int32(common.HeaderType_ENDORSER_TRANSACTION),
})
chaincodeDataBytes := protoMarshal(&peer.ChaincodeData{
Data: []byte("a-big-bunch-of-fakery"),
Id: []byte("a-friendly-fake-chaincode"),
Escc: "escc",
Vscc: "vscc",
Name: lo.Name,
Version: lo.Version,
InstantiationPolicy: instantiationPolicy,
Policy: nil, // EndorsementPolicy deliberately left nil
})
proposalPayloadBytes := protoMarshal(&peer.ChaincodeProposalPayload{
Input: protoMarshal(&peer.ChaincodeInvocationSpec{
ChaincodeSpec: &peer.ChaincodeSpec{
Input: &peer.ChaincodeInput{
Args: [][]byte{
[]byte(lo.Operation),
[]byte(lo.ChannelID),
protoMarshal(&peer.ChaincodeDeploymentSpec{
ChaincodeSpec: &peer.ChaincodeSpec{
ChaincodeId: &peer.ChaincodeID{
Name: lo.Name,
Version: lo.Version,
},
Input: &peer.ChaincodeInput{
Args: [][]byte{[]byte("bogus-init-arg")},
},
Type: peer.ChaincodeSpec_GOLANG,
},
}),
{}, // Endorsement policy bytes deliberately empty
[]byte("escc"),
[]byte("vscc"),
},
},
Type: peer.ChaincodeSpec_GOLANG,
},
}),
})
propHash := sha256.New()
propHash.Write(channelHeaderBytes)
propHash.Write(signatureHeaderBytes)
propHash.Write(proposalPayloadBytes)
proposalHash := propHash.Sum(nil)[:]
proposalResponsePayloadBytes := protoMarshal(&peer.ProposalResponsePayload{
ProposalHash: proposalHash,
Extension: protoMarshal(&peer.ChaincodeAction{
ChaincodeId: &peer.ChaincodeID{
Name: "lscc",
Version: "syscc",
},
Events: protoMarshal(&peer.ChaincodeEvent{
ChaincodeId: "lscc",
EventName: lo.Operation,
Payload: protoMarshal(&peer.LifecycleEvent{
ChaincodeName: lo.Name,
}),
}),
Response: &peer.Response{
Payload: chaincodeDataBytes,
Status: 200,
},
Results: protoMarshal(&rwset.TxReadWriteSet{
DataModel: rwset.TxReadWriteSet_KV,
NsRwset: []*rwset.NsReadWriteSet{
{
Namespace: "lscc",
Rwset: protoMarshal(&kvrwset.KVRWSet{
Writes: []*kvrwset.KVWrite{
{
Key: lo.Name,
Value: chaincodeDataBytes,
},
},
}),
},
{
Namespace: lo.Name,
Rwset: protoMarshal(&kvrwset.KVRWSet{
Writes: []*kvrwset.KVWrite{
{
Key: "bogus-key",
Value: []byte("bogus-value"),
},
},
}),
},
},
}),
}),
})
endorsementSignature, err := signer.Sign(append(proposalResponsePayloadBytes, creatorBytes...))
Expect(err).NotTo(HaveOccurred())
payloadBytes := protoMarshal(&common.Payload{
Header: &common.Header{
ChannelHeader: channelHeaderBytes,
SignatureHeader: signatureHeaderBytes,
},
Data: protoMarshal(&peer.Transaction{
Actions: []*peer.TransactionAction{
{
Header: signatureHeaderBytes,
Payload: protoMarshal(&peer.ChaincodeActionPayload{
ChaincodeProposalPayload: proposalPayloadBytes,
Action: &peer.ChaincodeEndorsedAction{
ProposalResponsePayload: proposalResponsePayloadBytes,
Endorsements: []*peer.Endorsement{
{
Endorser: creatorBytes,
Signature: endorsementSignature,
},
},
},
}),
},
},
}),
})
envSignature, err := signer.Sign(payloadBytes)
Expect(err).NotTo(HaveOccurred())
return &common.Envelope{
Payload: payloadBytes,
Signature: envSignature,
}
}
func protoMarshal(msg proto.Message) []byte {
b, err := proto.Marshal(msg)
Expect(err).NotTo(HaveOccurred())
return b
}