github.com/onflow/flow-go@v0.35.7-crescendo-preview.23-atree-inlining/engine/common/rpc/convert/execution_data_test.go (about) 1 package convert_test 2 3 import ( 4 "testing" 5 6 "github.com/stretchr/testify/assert" 7 "github.com/stretchr/testify/require" 8 9 "github.com/onflow/cadence/encoding/ccf" 10 jsoncdc "github.com/onflow/cadence/encoding/json" 11 "github.com/onflow/flow/protobuf/go/flow/entities" 12 13 "github.com/onflow/flow-go/engine/common/rpc/convert" 14 "github.com/onflow/flow-go/ledger/common/testutils" 15 "github.com/onflow/flow-go/model/flow" 16 "github.com/onflow/flow-go/module/executiondatasync/execution_data" 17 "github.com/onflow/flow-go/utils/unittest" 18 "github.com/onflow/flow-go/utils/unittest/generator" 19 ) 20 21 func TestConvertBlockExecutionDataEventPayloads(t *testing.T) { 22 // generators will produce identical event payloads (before encoding) 23 ccfEvents := generator.GetEventsWithEncoding(3, entities.EventEncodingVersion_CCF_V0) 24 jsonEvents := make([]flow.Event, len(ccfEvents)) 25 for i, e := range ccfEvents { 26 jsonEvent, err := convert.CcfEventToJsonEvent(e) 27 require.NoError(t, err) 28 jsonEvents[i] = *jsonEvent 29 } 30 31 // generate BlockExecutionData with CCF encoded events 32 executionData := unittest.BlockExecutionDataFixture( 33 unittest.WithChunkExecutionDatas( 34 unittest.ChunkExecutionDataFixture(t, 1024, unittest.WithChunkEvents(ccfEvents)), 35 unittest.ChunkExecutionDataFixture(t, 1024, unittest.WithChunkEvents(ccfEvents)), 36 ), 37 ) 38 39 execDataMessage, err := convert.BlockExecutionDataToMessage(executionData) 40 require.NoError(t, err) 41 42 t.Run("regular convert does not modify payload encoding", func(t *testing.T) { 43 for _, chunk := range execDataMessage.GetChunkExecutionData() { 44 events := convert.MessagesToEvents(chunk.Events) 45 for i, e := range events { 46 assert.Equal(t, ccfEvents[i], e) 47 48 _, err := ccf.Decode(nil, e.Payload) 49 require.NoError(t, err) 50 } 51 } 52 }) 53 54 t.Run("converted event payloads are encoded in jsoncdc", func(t *testing.T) { 55 err = convert.BlockExecutionDataEventPayloadsToVersion(execDataMessage, entities.EventEncodingVersion_JSON_CDC_V0) 56 require.NoError(t, err) 57 58 for _, chunk := range execDataMessage.GetChunkExecutionData() { 59 events := convert.MessagesToEvents(chunk.Events) 60 for i, e := range events { 61 assert.Equal(t, jsonEvents[i], e) 62 63 _, err := jsoncdc.Decode(nil, e.Payload) 64 require.NoError(t, err) 65 } 66 } 67 }) 68 } 69 70 func TestConvertBlockExecutionData(t *testing.T) { 71 t.Parallel() 72 73 chain := flow.Testnet.Chain() // this is used by the AddressFixture 74 events := unittest.EventsFixture(5) 75 76 chunks := 5 77 chunkData := make([]*execution_data.ChunkExecutionData, 0, chunks) 78 for i := 0; i < chunks-1; i++ { 79 ced := unittest.ChunkExecutionDataFixture(t, 80 0, // updates set explicitly to target 160-320KB per chunk 81 unittest.WithChunkEvents(events), 82 unittest.WithTrieUpdate(testutils.TrieUpdateFixture(5, 32*1024, 64*1024)), 83 ) 84 85 chunkData = append(chunkData, ced) 86 } 87 makeServiceTx := func(ced *execution_data.ChunkExecutionData) { 88 // proposal key and payer are empty addresses for service tx 89 collection := unittest.CollectionFixture(1) 90 collection.Transactions[0].ProposalKey.Address = flow.EmptyAddress 91 collection.Transactions[0].Payer = flow.EmptyAddress 92 ced.Collection = &collection 93 94 // the service chunk sometimes does not have any trie updates 95 ced.TrieUpdate = nil 96 } 97 chunk := unittest.ChunkExecutionDataFixture(t, execution_data.DefaultMaxBlobSize/5, unittest.WithChunkEvents(events), makeServiceTx) 98 chunkData = append(chunkData, chunk) 99 100 blockData := unittest.BlockExecutionDataFixture(unittest.WithChunkExecutionDatas(chunkData...)) 101 102 msg, err := convert.BlockExecutionDataToMessage(blockData) 103 require.NoError(t, err) 104 105 converted, err := convert.MessageToBlockExecutionData(msg, chain) 106 require.NoError(t, err) 107 108 assert.Equal(t, blockData, converted) 109 for i, chunk := range blockData.ChunkExecutionDatas { 110 if chunk.TrieUpdate == nil { 111 assert.Nil(t, converted.ChunkExecutionDatas[i].TrieUpdate) 112 } else { 113 assert.True(t, chunk.TrieUpdate.Equals(converted.ChunkExecutionDatas[i].TrieUpdate)) 114 } 115 } 116 } 117 118 func TestConvertChunkExecutionData(t *testing.T) { 119 tests := []struct { 120 name string 121 fn func(*testing.T) *execution_data.ChunkExecutionData 122 }{ 123 { 124 name: "chunk execution data conversions", 125 fn: func(t *testing.T) *execution_data.ChunkExecutionData { 126 return unittest.ChunkExecutionDataFixture(t, 127 0, // updates set explicitly to target 160-320KB per chunk 128 unittest.WithChunkEvents(unittest.EventsFixture(5)), 129 unittest.WithTrieUpdate(testutils.TrieUpdateFixture(5, 32*1024, 64*1024)), 130 ) 131 }, 132 }, 133 { 134 name: "chunk execution data conversions - no events", 135 fn: func(t *testing.T) *execution_data.ChunkExecutionData { 136 ced := unittest.ChunkExecutionDataFixture(t, 0) 137 ced.Events = nil 138 return ced 139 }, 140 }, 141 { 142 name: "chunk execution data conversions - no trie update", 143 fn: func(t *testing.T) *execution_data.ChunkExecutionData { 144 ced := unittest.ChunkExecutionDataFixture(t, 0) 145 ced.TrieUpdate = nil 146 return ced 147 }, 148 }, 149 { 150 name: "chunk execution data conversions - empty collection", 151 fn: func(t *testing.T) *execution_data.ChunkExecutionData { 152 ced := unittest.ChunkExecutionDataFixture(t, 0) 153 ced.Collection = &flow.Collection{} 154 ced.TransactionResults = nil 155 return ced 156 }, 157 }, 158 } 159 160 for _, test := range tests { 161 t.Run(test.name, func(t *testing.T) { 162 ced := test.fn(t) 163 164 chunkMsg, err := convert.ChunkExecutionDataToMessage(ced) 165 require.NoError(t, err) 166 167 chunkReConverted, err := convert.MessageToChunkExecutionData(chunkMsg, flow.Testnet.Chain()) 168 require.NoError(t, err) 169 170 assert.Equal(t, ced, chunkReConverted) 171 if ced.TrieUpdate == nil { 172 assert.Nil(t, chunkReConverted.TrieUpdate) 173 } else { 174 assert.True(t, ced.TrieUpdate.Equals(chunkReConverted.TrieUpdate)) 175 } 176 }) 177 } 178 } 179 180 func TestMessageToRegisterID(t *testing.T) { 181 chain := flow.Testnet.Chain() 182 tests := []struct { 183 name string 184 regID flow.RegisterID 185 }{ 186 { 187 name: "service level register id", 188 regID: flow.UUIDRegisterID(0), 189 }, 190 { 191 name: "account level register id", 192 regID: flow.AccountStatusRegisterID(unittest.AddressFixture()), 193 }, 194 { 195 name: "regular register id", 196 regID: unittest.RegisterIDFixture(), 197 }, 198 } 199 200 for _, test := range tests { 201 t.Run(test.name, func(t *testing.T) { 202 msg := convert.RegisterIDToMessage(test.regID) 203 converted, err := convert.MessageToRegisterID(msg, chain) 204 require.NoError(t, err) 205 assert.Equal(t, test.regID, converted) 206 }) 207 } 208 209 t.Run("nil owner converts to empty string", func(t *testing.T) { 210 msg := &entities.RegisterID{ 211 Owner: nil, 212 Key: []byte("key"), 213 } 214 converted, err := convert.MessageToRegisterID(msg, chain) 215 require.NoError(t, err) 216 assert.Equal(t, "", converted.Owner) 217 assert.Equal(t, "key", converted.Key) 218 }) 219 220 t.Run("nil message returns error", func(t *testing.T) { 221 _, err := convert.MessageToRegisterID(nil, chain) 222 require.ErrorIs(t, err, convert.ErrEmptyMessage) 223 }) 224 225 t.Run("invalid address returns error", func(t *testing.T) { 226 // addresses for other chains are invalid 227 registerID := flow.NewRegisterID( 228 unittest.RandomAddressFixtureForChain(flow.Mainnet), 229 "key", 230 ) 231 232 msg := convert.RegisterIDToMessage(registerID) 233 _, err := convert.MessageToRegisterID(msg, chain) 234 require.Error(t, err) 235 }) 236 237 t.Run("multiple registerIDs", func(t *testing.T) { 238 expected := flow.RegisterIDs{ 239 flow.UUIDRegisterID(0), 240 flow.AccountStatusRegisterID(unittest.AddressFixture()), 241 unittest.RegisterIDFixture(), 242 } 243 244 messages := make([]*entities.RegisterID, len(expected)) 245 for i, regID := range expected { 246 regID := regID 247 messages[i] = convert.RegisterIDToMessage(regID) 248 require.Equal(t, regID.Owner, string(messages[i].Owner)) 249 require.Equal(t, regID.Key, string(messages[i].Key)) 250 } 251 252 actual, err := convert.MessagesToRegisterIDs(messages, chain) 253 require.NoError(t, err) 254 assert.Equal(t, expected, actual) 255 }) 256 }