diff --git a/integration/nwo/network.go b/integration/nwo/network.go index 0732fafaab3..8df71903c46 100644 --- a/integration/nwo/network.go +++ b/integration/nwo/network.go @@ -41,6 +41,14 @@ import ( "gopkg.in/yaml.v2" ) +// Blocks defines block cutting config. +type Blocks struct { + BatchTimeout int `yaml:"batch_timeout,omitempty"` + MaxMessageCount int `yaml:"max_message_count,omitempty"` + AbsoluteMaxBytes int `yaml:"absolute_max_bytes,omitempty"` + PreferredMaxBytes int `yaml:"preferred_max_bytes,omitempty"` +} + // Organization models information about an Organization. It includes // the information needed to populate an MSP with cryptogen. type Organization struct { @@ -135,6 +143,7 @@ type Profile struct { Organizations []string `yaml:"organizations,omitempty"` AppCapabilities []string `yaml:"app_capabilities,omitempty"` ChannelCapabilities []string `yaml:"channel_capabilities,omitempty"` + Blocks *Blocks `yaml:"blocks,omitempty"` } // Network holds information about a fabric network. diff --git a/integration/nwo/template/configtx_template.go b/integration/nwo/template/configtx_template.go index 0b1c0803b39..4ad51b07532 100644 --- a/integration/nwo/template/configtx_template.go +++ b/integration/nwo/template/configtx_template.go @@ -144,11 +144,19 @@ Profiles:{{ range .Profiles }} Addresses:{{ range .Orderers }}{{ with $w.Orderer . }} - 127.0.0.1:{{ $w.OrdererPort . "Listen" }} {{- end }}{{ end }} + {{- if .Blocks}} + BatchTimeout: {{ .Blocks.BatchTimeout }}s + BatchSize: + MaxMessageCount: {{ .Blocks.MaxMessageCount }} + AbsoluteMaxBytes: {{ .Blocks.AbsoluteMaxBytes }} MB + PreferredMaxBytes: {{ .Blocks.PreferredMaxBytes }} KB + {{- else }} BatchTimeout: 1s BatchSize: MaxMessageCount: 1 AbsoluteMaxBytes: 98 MB PreferredMaxBytes: 512 KB + {{- end}} Capabilities: {{- if eq $w.Consensus.Type "BFT" }} V3_0: true diff --git a/integration/pvtdata/data_purge_test.go b/integration/pvtdata/data_purge_test.go index 16116102b79..c19d1f0be83 100644 --- a/integration/pvtdata/data_purge_test.go +++ b/integration/pvtdata/data_purge_test.go @@ -13,6 +13,7 @@ import ( "io/ioutil" "os" "path/filepath" + "sync" "syscall" "github.com/golang/protobuf/proto" @@ -31,6 +32,7 @@ import ( var _ = Describe("Pvtdata purge", func() { var ( + config *nwo.Config applicationCapabilitiesVersion string testDir string network *nwo.Network @@ -46,7 +48,6 @@ var _ = Describe("Pvtdata purge", func() { testDir, err = ioutil.TempDir("", "purgedata") Expect(err).NotTo(HaveOccurred()) - config := nwo.ThreeOrgEtcdRaft() network = nwo.New(config, testDir, nil, StartPort(), components) network.GenerateConfigTree() @@ -110,6 +111,7 @@ var _ = Describe("Pvtdata purge", func() { When("the purge private data capability is not enabled", func() { BeforeEach(func() { + config = nwo.ThreeOrgEtcdRaft() applicationCapabilitiesVersion = "V2_0" }) @@ -134,17 +136,87 @@ var _ = Describe("Pvtdata purge", func() { When("the purge private data capability is enabled", func() { BeforeEach(func() { + config = nwo.ThreeOrgEtcdRaft() + config.Profiles[0].Blocks = &nwo.Blocks{ + BatchTimeout: 6, + MaxMessageCount: 30, + AbsoluteMaxBytes: 99, + PreferredMaxBytes: 512, + } applicationCapabilitiesVersion = "V2_5" }) It("should prevent purged data being included in responses after the purge transaction has been committed", func() { - marblechaincodeutil.AssertPresentInCollectionM(network, channelID, chaincode.Name, `test-marble-0`, org2Peer0) + marblechaincodeutil.AddMarble(network, orderer, channelID, chaincode.Name, `{"name":"test-marble-1", "color":"green", "size":42, "owner":"simon", "price":180}`, org2Peer0) + marblechaincodeutil.AddMarble(network, orderer, channelID, chaincode.Name, `{"name":"test-marble-2", "color":"red", "size":24, "owner":"heather", "price":635}`, org2Peer0) + marblechaincodeutil.AddMarble(network, orderer, channelID, chaincode.Name, `{"name":"test-marble-3", "color":"black", "size":12, "owner":"bob", "price":2}`, org2Peer0) + marblechaincodeutil.AddMarble(network, orderer, channelID, chaincode.Name, `{"name":"test-marble-4", "color":"yellow", "size":180, "owner":"liz", "price":100}`, org2Peer0) + marblechaincodeutil.AddMarble(network, orderer, channelID, chaincode.Name, `{"name":"test-marble-5", "color":"pink", "size":60, "owner":"joe", "price":999}`, org2Peer0) + marblechaincodeutil.AddMarble(network, orderer, channelID, chaincode.Name, `{"name":"test-marble-6", "color":"purple", "size":1, "owner":"clive", "price":1984}`, org2Peer0) + + marblechaincodeutil.AssertPresentInCollectionM(network, channelID, chaincode.Name, "test-marble-0", org2Peer0) marblechaincodeutil.AssertPresentInCollectionMPD(network, channelID, chaincode.Name, "test-marble-0", org2Peer0) + marblechaincodeutil.AssertPresentInCollectionM(network, channelID, chaincode.Name, "test-marble-1", org2Peer0) + marblechaincodeutil.AssertPresentInCollectionMPD(network, channelID, chaincode.Name, "test-marble-1", org2Peer0) + marblechaincodeutil.AssertPresentInCollectionM(network, channelID, chaincode.Name, "test-marble-2", org2Peer0) + marblechaincodeutil.AssertPresentInCollectionMPD(network, channelID, chaincode.Name, "test-marble-2", org2Peer0) + marblechaincodeutil.AssertPresentInCollectionM(network, channelID, chaincode.Name, "test-marble-3", org2Peer0) + marblechaincodeutil.AssertPresentInCollectionMPD(network, channelID, chaincode.Name, "test-marble-3", org2Peer0) + marblechaincodeutil.AssertPresentInCollectionM(network, channelID, chaincode.Name, "test-marble-4", org2Peer0) + marblechaincodeutil.AssertPresentInCollectionMPD(network, channelID, chaincode.Name, "test-marble-4", org2Peer0) + marblechaincodeutil.AssertPresentInCollectionM(network, channelID, chaincode.Name, "test-marble-5", org2Peer0) + marblechaincodeutil.AssertPresentInCollectionMPD(network, channelID, chaincode.Name, "test-marble-5", org2Peer0) + marblechaincodeutil.AssertPresentInCollectionM(network, channelID, chaincode.Name, "test-marble-6", org2Peer0) + marblechaincodeutil.AssertPresentInCollectionMPD(network, channelID, chaincode.Name, "test-marble-6", org2Peer0) marblechaincodeutil.PurgeMarble(network, orderer, channelID, chaincode.Name, `{"name":"test-marble-0"}`, org2Peer0) - - marblechaincodeutil.AssertDoesNotExistInCollectionM(network, channelID, chaincode.Name, `test-marble-0`, org2Peer0) - marblechaincodeutil.AssertDoesNotExistInCollectionMPD(network, channelID, chaincode.Name, `test-marble-0`, org2Peer0) + marblechaincodeutil.PurgeMarble(network, orderer, channelID, chaincode.Name, `{"name":"test-marble-1"}`, org2Peer0) + + marblechaincodeutil.AssertDoesNotExistInCollectionM(network, channelID, chaincode.Name, "test-marble-0", org2Peer0) + marblechaincodeutil.AssertDoesNotExistInCollectionMPD(network, channelID, chaincode.Name, "test-marble-0", org2Peer0) + marblechaincodeutil.AssertDoesNotExistInCollectionM(network, channelID, chaincode.Name, "test-marble-1", org2Peer0) + marblechaincodeutil.AssertDoesNotExistInCollectionMPD(network, channelID, chaincode.Name, "test-marble-1", org2Peer0) + + marblechaincodeutil.AssertPresentInCollectionM(network, channelID, chaincode.Name, "test-marble-2", org2Peer0) + marblechaincodeutil.AssertPresentInCollectionMPD(network, channelID, chaincode.Name, "test-marble-2", org2Peer0) + marblechaincodeutil.AssertPresentInCollectionM(network, channelID, chaincode.Name, "test-marble-3", org2Peer0) + marblechaincodeutil.AssertPresentInCollectionMPD(network, channelID, chaincode.Name, "test-marble-3", org2Peer0) + marblechaincodeutil.AssertPresentInCollectionM(network, channelID, chaincode.Name, "test-marble-4", org2Peer0) + marblechaincodeutil.AssertPresentInCollectionMPD(network, channelID, chaincode.Name, "test-marble-4", org2Peer0) + marblechaincodeutil.AssertPresentInCollectionM(network, channelID, chaincode.Name, "test-marble-5", org2Peer0) + marblechaincodeutil.AssertPresentInCollectionMPD(network, channelID, chaincode.Name, "test-marble-5", org2Peer0) + marblechaincodeutil.AssertPresentInCollectionM(network, channelID, chaincode.Name, "test-marble-6", org2Peer0) + marblechaincodeutil.AssertPresentInCollectionMPD(network, channelID, chaincode.Name, "test-marble-6", org2Peer0) + + // Purge multiple marbles in a single block + var wg sync.WaitGroup + wg.Add(5) + for i := 2; i < 7; i++ { + go func(marblePurge string) { + defer GinkgoRecover() + defer wg.Done() + marblechaincodeutil.PurgeMarble(network, orderer, channelID, chaincode.Name, marblePurge, org2Peer0) + }(fmt.Sprintf(`{"name":"test-marble-%d"}`, i)) + } + wg.Wait() + Expect(nwo.GetLedgerHeight(network, org2Peer0, channelID)).To(Equal(19)) + + marblechaincodeutil.AssertDoesNotExistInCollectionM(network, channelID, chaincode.Name, "test-marble-0", org2Peer0) + marblechaincodeutil.AssertDoesNotExistInCollectionMPD(network, channelID, chaincode.Name, "test-marble-0", org2Peer0) + marblechaincodeutil.AssertDoesNotExistInCollectionM(network, channelID, chaincode.Name, "test-marble-1", org2Peer0) + marblechaincodeutil.AssertDoesNotExistInCollectionMPD(network, channelID, chaincode.Name, "test-marble-1", org2Peer0) + marblechaincodeutil.AssertDoesNotExistInCollectionM(network, channelID, chaincode.Name, "test-marble-2", org2Peer0) + marblechaincodeutil.AssertDoesNotExistInCollectionMPD(network, channelID, chaincode.Name, "test-marble-2", org2Peer0) + marblechaincodeutil.AssertDoesNotExistInCollectionM(network, channelID, chaincode.Name, "test-marble-3", org2Peer0) + marblechaincodeutil.AssertDoesNotExistInCollectionMPD(network, channelID, chaincode.Name, "test-marble-3", org2Peer0) + marblechaincodeutil.AssertDoesNotExistInCollectionM(network, channelID, chaincode.Name, "test-marble-4", org2Peer0) + marblechaincodeutil.AssertDoesNotExistInCollectionMPD(network, channelID, chaincode.Name, "test-marble-4", org2Peer0) + marblechaincodeutil.AssertDoesNotExistInCollectionM(network, channelID, chaincode.Name, "test-marble-5", org2Peer0) + marblechaincodeutil.AssertDoesNotExistInCollectionMPD(network, channelID, chaincode.Name, "test-marble-5", org2Peer0) + marblechaincodeutil.AssertDoesNotExistInCollectionM(network, channelID, chaincode.Name, "test-marble-6", org2Peer0) + marblechaincodeutil.AssertDoesNotExistInCollectionMPD(network, channelID, chaincode.Name, "test-marble-6", org2Peer0) + marblechaincodeutil.AssertDoesNotExistInCollectionM(network, channelID, chaincode.Name, "test-marble-7", org2Peer0) + marblechaincodeutil.AssertDoesNotExistInCollectionMPD(network, channelID, chaincode.Name, "test-marble-7", org2Peer0) }) It("should prevent purged data being included block event replays after the purge transaction has been committed", func() { @@ -167,9 +239,6 @@ var _ = Describe("Pvtdata purge", func() { assertBlockEventsOnlyContainUnpurgedPrivateData(network, org2Peer0, chaincode.Name, []string{"test-marble-10", "\x00color~name\x00green\x00test-marble-10\x00", "test-marble-100", "\x00color~name\x00red\x00test-marble-100\x00"}) }) - // 1. User is able to submit a purge transaction that involves more than one keys - PIt("should accept multiple keys for purging in the same transaction") - // 2. The endorsement policy is evaluated correctly for a purge transaction under // different endorsement policy settings (e.g., collection level/ key-hash based) // Note: The endorsement policy level tests need not to be prioritized over other @@ -203,13 +272,6 @@ var _ = Describe("Pvtdata purge", func() { }) PIt("should correctly enforce other endorsement policies (TBC)") - // 3. Data is purged on an eligible peer - // - Add a few keys into a collection - // - Issue a purge transaction for some of the keys - // - Verify that all the versions of the intended keys are purged while the remaining keys still exist - // - Repeat above to purge all keys to test the corner case - PIt("should remove all purged data from an eligible peer") - // 4. Data is purged on previously eligible but now ineligible peer // - Add a few keys into a collection // - Submit a collection config update to remove an org