Skip to content

Commit 69c8d72

Browse files
authored
Merge pull request #540 from CosmWasm/chipshort/migrate-version
Contract Migrate Version
2 parents 1c3fdc2 + 9ce2011 commit 69c8d72

12 files changed

+938
-316
lines changed

ibc_test.go

+2
Original file line numberDiff line numberDiff line change
@@ -302,6 +302,7 @@ func TestAnalyzeCode(t *testing.T) {
302302
require.NoError(t, err)
303303
require.False(t, report.HasIBCEntryPoints)
304304
require.Equal(t, "", report.RequiredCapabilities)
305+
require.Equal(t, uint64(42), *report.ContractMigrateVersion)
305306

306307
// Store IBC contract
307308
wasm2, err := os.ReadFile(IBC_TEST_CONTRACT)
@@ -313,6 +314,7 @@ func TestAnalyzeCode(t *testing.T) {
313314
require.NoError(t, err)
314315
require.True(t, report2.HasIBCEntryPoints)
315316
require.Equal(t, "iterator,stargate", report2.RequiredCapabilities)
317+
require.Nil(t, report2.ContractMigrateVersion)
316318
}
317319

318320
func TestIBCMsgGetChannel(t *testing.T) {

internal/api/bindings.h

+15
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,14 @@ typedef struct UnmanagedVector {
194194
uintptr_t cap;
195195
} UnmanagedVector;
196196

197+
/**
198+
* A version of `Option<u64>` that can be used safely in FFI.
199+
*/
200+
typedef struct OptionalU64 {
201+
bool is_some;
202+
uint64_t value;
203+
} OptionalU64;
204+
197205
/**
198206
* The result type of the FFI function analyze_code.
199207
*
@@ -217,6 +225,13 @@ typedef struct AnalysisReport {
217225
* This is never None/nil.
218226
*/
219227
struct UnmanagedVector required_capabilities;
228+
/**
229+
* The migrate version of the contract.
230+
* This is None if the contract does not have a migrate version and the `migrate` entrypoint
231+
* needs to be called for every migration (if present).
232+
* If it is `Some(version)`, it only needs to be called if the `version` increased.
233+
*/
234+
struct OptionalU64 contract_migrate_version;
220235
} AnalysisReport;
221236

222237
typedef struct Metrics {

internal/api/lib.go

+5-3
Original file line numberDiff line numberDiff line change
@@ -161,10 +161,12 @@ func AnalyzeCode(cache Cache, checksum []byte) (*types.AnalysisReport, error) {
161161
}
162162
requiredCapabilities := string(copyAndDestroyUnmanagedVector(report.required_capabilities))
163163
entrypoints := string(copyAndDestroyUnmanagedVector(report.entrypoints))
164+
164165
res := types.AnalysisReport{
165-
HasIBCEntryPoints: bool(report.has_ibc_entry_points),
166-
RequiredCapabilities: requiredCapabilities,
167-
Entrypoints: strings.Split(entrypoints, ","),
166+
HasIBCEntryPoints: bool(report.has_ibc_entry_points),
167+
RequiredCapabilities: requiredCapabilities,
168+
Entrypoints: strings.Split(entrypoints, ","),
169+
ContractMigrateVersion: optionalU64ToPtr(report.contract_migrate_version),
168170
}
169171
return &res, nil
170172
}

internal/api/lib_test.go

+17-17
Original file line numberDiff line numberDiff line change
@@ -305,7 +305,7 @@ func TestGetMetrics(t *testing.T) {
305305
require.Equal(t, uint32(0), metrics.HitsMemoryCache)
306306
require.Equal(t, uint32(1), metrics.HitsFsCache)
307307
require.Equal(t, uint64(1), metrics.ElementsMemoryCache)
308-
require.InEpsilon(t, 2832576, metrics.SizeMemoryCache, 0.25)
308+
require.InEpsilon(t, 3700000, metrics.SizeMemoryCache, 0.25)
309309

310310
// Instantiate 2
311311
msg2 := []byte(`{"verifier": "fred", "beneficiary": "susi"}`)
@@ -318,7 +318,7 @@ func TestGetMetrics(t *testing.T) {
318318
require.Equal(t, uint32(1), metrics.HitsMemoryCache)
319319
require.Equal(t, uint32(1), metrics.HitsFsCache)
320320
require.Equal(t, uint64(1), metrics.ElementsMemoryCache)
321-
require.InEpsilon(t, 2832576, metrics.SizeMemoryCache, 0.25)
321+
require.InEpsilon(t, 3700000, metrics.SizeMemoryCache, 0.25)
322322

323323
// Pin
324324
err = Pin(cache, checksum)
@@ -331,8 +331,8 @@ func TestGetMetrics(t *testing.T) {
331331
require.Equal(t, uint32(2), metrics.HitsFsCache)
332332
require.Equal(t, uint64(1), metrics.ElementsPinnedMemoryCache)
333333
require.Equal(t, uint64(1), metrics.ElementsMemoryCache)
334-
require.InEpsilon(t, 2832576, metrics.SizePinnedMemoryCache, 0.25)
335-
require.InEpsilon(t, 2832576, metrics.SizeMemoryCache, 0.25)
334+
require.InEpsilon(t, 3700000, metrics.SizePinnedMemoryCache, 0.25)
335+
require.InEpsilon(t, 3700000, metrics.SizeMemoryCache, 0.25)
336336

337337
// Instantiate 3
338338
msg3 := []byte(`{"verifier": "fred", "beneficiary": "bert"}`)
@@ -347,8 +347,8 @@ func TestGetMetrics(t *testing.T) {
347347
require.Equal(t, uint32(2), metrics.HitsFsCache)
348348
require.Equal(t, uint64(1), metrics.ElementsPinnedMemoryCache)
349349
require.Equal(t, uint64(1), metrics.ElementsMemoryCache)
350-
require.InEpsilon(t, 2832576, metrics.SizePinnedMemoryCache, 0.25)
351-
require.InEpsilon(t, 2832576, metrics.SizeMemoryCache, 0.25)
350+
require.InEpsilon(t, 3700000, metrics.SizePinnedMemoryCache, 0.25)
351+
require.InEpsilon(t, 3700000, metrics.SizeMemoryCache, 0.25)
352352

353353
// Unpin
354354
err = Unpin(cache, checksum)
@@ -363,7 +363,7 @@ func TestGetMetrics(t *testing.T) {
363363
require.Equal(t, uint64(0), metrics.ElementsPinnedMemoryCache)
364364
require.Equal(t, uint64(1), metrics.ElementsMemoryCache)
365365
require.Equal(t, uint64(0), metrics.SizePinnedMemoryCache)
366-
require.InEpsilon(t, 2832576, metrics.SizeMemoryCache, 0.25)
366+
require.InEpsilon(t, 3700000, metrics.SizeMemoryCache, 0.25)
367367

368368
// Instantiate 4
369369
msg4 := []byte(`{"verifier": "fred", "beneficiary": "jeff"}`)
@@ -379,7 +379,7 @@ func TestGetMetrics(t *testing.T) {
379379
require.Equal(t, uint64(0), metrics.ElementsPinnedMemoryCache)
380380
require.Equal(t, uint64(1), metrics.ElementsMemoryCache)
381381
require.Equal(t, uint64(0), metrics.SizePinnedMemoryCache)
382-
require.InEpsilon(t, 2832576, metrics.SizeMemoryCache, 0.25)
382+
require.InEpsilon(t, 3700000, metrics.SizeMemoryCache, 0.25)
383383
}
384384

385385
func TestInstantiate(t *testing.T) {
@@ -405,7 +405,7 @@ func TestInstantiate(t *testing.T) {
405405
res, cost, err := Instantiate(cache, checksum, env, info, msg, &igasMeter, store, api, &querier, TESTING_GAS_LIMIT, TESTING_PRINT_DEBUG)
406406
require.NoError(t, err)
407407
requireOkResponse(t, res, 0)
408-
assert.Equal(t, uint64(0x5088ea), cost.UsedInternally)
408+
assert.Equal(t, uint64(0x540eb6), cost.UsedInternally)
409409

410410
var result types.ContractResult
411411
err = json.Unmarshal(res, &result)
@@ -436,7 +436,7 @@ func TestExecute(t *testing.T) {
436436
diff := time.Since(start)
437437
require.NoError(t, err)
438438
requireOkResponse(t, res, 0)
439-
assert.Equal(t, uint64(0x5088ea), cost.UsedInternally)
439+
assert.Equal(t, uint64(0x540eb6), cost.UsedInternally)
440440
t.Logf("Time (%d gas): %s\n", cost.UsedInternally, diff)
441441

442442
// execute with the same store
@@ -449,7 +449,7 @@ func TestExecute(t *testing.T) {
449449
res, cost, err = Execute(cache, checksum, env, info, []byte(`{"release":{}}`), &igasMeter2, store, api, &querier, TESTING_GAS_LIMIT, TESTING_PRINT_DEBUG)
450450
diff = time.Since(start)
451451
require.NoError(t, err)
452-
assert.Equal(t, uint64(0x8be9c6), cost.UsedInternally)
452+
assert.Equal(t, uint64(0x975216), cost.UsedInternally)
453453
t.Logf("Time (%d gas): %s\n", cost.UsedInternally, diff)
454454

455455
// make sure it read the balance properly and we got 250 atoms
@@ -557,7 +557,7 @@ func TestExecuteCpuLoop(t *testing.T) {
557557
diff := time.Since(start)
558558
require.NoError(t, err)
559559
requireOkResponse(t, res, 0)
560-
assert.Equal(t, uint64(0x365a42), cost.UsedInternally)
560+
assert.Equal(t, uint64(0x3d997e), cost.UsedInternally)
561561
t.Logf("Time (%d gas): %s\n", cost.UsedInternally, diff)
562562

563563
// execute a cpu loop
@@ -786,7 +786,7 @@ func TestMultipleInstances(t *testing.T) {
786786
require.NoError(t, err)
787787
requireOkResponse(t, res, 0)
788788
// we now count wasm gas charges and db writes
789-
assert.Equal(t, uint64(0x4ffce0), cost.UsedInternally)
789+
assert.Equal(t, uint64(0x53541c), cost.UsedInternally)
790790

791791
// instance2 controlled by mary
792792
gasMeter2 := NewMockGasMeter(TESTING_GAS_LIMIT)
@@ -797,14 +797,14 @@ func TestMultipleInstances(t *testing.T) {
797797
res, cost, err = Instantiate(cache, checksum, env, info, msg, &igasMeter2, store2, api, &querier, TESTING_GAS_LIMIT, TESTING_PRINT_DEBUG)
798798
require.NoError(t, err)
799799
requireOkResponse(t, res, 0)
800-
assert.Equal(t, uint64(0x504dbc), cost.UsedInternally)
800+
assert.Equal(t, uint64(0x53bbb4), cost.UsedInternally)
801801

802802
// fail to execute store1 with mary
803-
resp := exec(t, cache, checksum, "mary", store1, api, querier, 0x4a20c2)
803+
resp := exec(t, cache, checksum, "mary", store1, api, querier, 0x503f70)
804804
require.Equal(t, "Unauthorized", resp.Err)
805805

806806
// succeed to execute store1 with fred
807-
resp = exec(t, cache, checksum, "fred", store1, api, querier, 0x8ba826)
807+
resp = exec(t, cache, checksum, "fred", store1, api, querier, 0x970662)
808808
require.Equal(t, "", resp.Err)
809809
require.Equal(t, 1, len(resp.Ok.Messages))
810810
attributes := resp.Ok.Attributes
@@ -813,7 +813,7 @@ func TestMultipleInstances(t *testing.T) {
813813
require.Equal(t, "bob", attributes[1].Value)
814814

815815
// succeed to execute store2 with mary
816-
resp = exec(t, cache, checksum, "mary", store2, api, querier, 0x8bc8f6)
816+
resp = exec(t, cache, checksum, "mary", store2, api, querier, 0x972c3c)
817817
require.Equal(t, "", resp.Err)
818818
require.Equal(t, 1, len(resp.Ok.Messages))
819819
attributes = resp.Ok.Attributes

internal/api/memory.go

+7
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,13 @@ func copyAndDestroyUnmanagedVector(v C.UnmanagedVector) []byte {
7575
return out
7676
}
7777

78+
func optionalU64ToPtr(val C.OptionalU64) *uint64 {
79+
if val.is_some {
80+
return (*uint64)(&val.value)
81+
}
82+
return nil
83+
}
84+
7885
// copyU8Slice copies the contents of an Option<&[u8]> that was allocated on the Rust side.
7986
// Returns nil if and only if the source is None.
8087
func copyU8Slice(view C.U8SliceView) []byte {

lib_libwasmvm_test.go

+8-8
Original file line numberDiff line numberDiff line change
@@ -285,7 +285,7 @@ func TestGetMetrics(t *testing.T) {
285285
require.Equal(t, uint32(1), metrics.HitsFsCache)
286286
require.Equal(t, uint64(1), metrics.ElementsMemoryCache)
287287
t.Log(metrics.SizeMemoryCache)
288-
require.InEpsilon(t, 2832576, metrics.SizeMemoryCache, 0.25)
288+
require.InEpsilon(t, 3700000, metrics.SizeMemoryCache, 0.25)
289289

290290
// Instantiate 2
291291
msg2 := []byte(`{"verifier": "fred", "beneficiary": "susi"}`)
@@ -301,7 +301,7 @@ func TestGetMetrics(t *testing.T) {
301301
require.Equal(t, uint32(1), metrics.HitsMemoryCache)
302302
require.Equal(t, uint32(1), metrics.HitsFsCache)
303303
require.Equal(t, uint64(1), metrics.ElementsMemoryCache)
304-
require.InEpsilon(t, 2832576, metrics.SizeMemoryCache, 0.25)
304+
require.InEpsilon(t, 3700000, metrics.SizeMemoryCache, 0.25)
305305

306306
// Pin
307307
err = vm.Pin(checksum)
@@ -314,8 +314,8 @@ func TestGetMetrics(t *testing.T) {
314314
require.Equal(t, uint32(2), metrics.HitsFsCache)
315315
require.Equal(t, uint64(1), metrics.ElementsPinnedMemoryCache)
316316
require.Equal(t, uint64(1), metrics.ElementsMemoryCache)
317-
require.InEpsilon(t, 2832576, metrics.SizePinnedMemoryCache, 0.25)
318-
require.InEpsilon(t, 2832576, metrics.SizeMemoryCache, 0.25)
317+
require.InEpsilon(t, 3700000, metrics.SizePinnedMemoryCache, 0.25)
318+
require.InEpsilon(t, 3700000, metrics.SizeMemoryCache, 0.25)
319319

320320
// Instantiate 3
321321
msg3 := []byte(`{"verifier": "fred", "beneficiary": "bert"}`)
@@ -333,8 +333,8 @@ func TestGetMetrics(t *testing.T) {
333333
require.Equal(t, uint32(2), metrics.HitsFsCache)
334334
require.Equal(t, uint64(1), metrics.ElementsPinnedMemoryCache)
335335
require.Equal(t, uint64(1), metrics.ElementsMemoryCache)
336-
require.InEpsilon(t, 2832576, metrics.SizePinnedMemoryCache, 0.25)
337-
require.InEpsilon(t, 2832576, metrics.SizeMemoryCache, 0.25)
336+
require.InEpsilon(t, 3700000, metrics.SizePinnedMemoryCache, 0.25)
337+
require.InEpsilon(t, 3700000, metrics.SizeMemoryCache, 0.25)
338338

339339
// Unpin
340340
err = vm.Unpin(checksum)
@@ -349,7 +349,7 @@ func TestGetMetrics(t *testing.T) {
349349
require.Equal(t, uint64(0), metrics.ElementsPinnedMemoryCache)
350350
require.Equal(t, uint64(1), metrics.ElementsMemoryCache)
351351
require.Equal(t, uint64(0), metrics.SizePinnedMemoryCache)
352-
require.InEpsilon(t, 2832576, metrics.SizeMemoryCache, 0.25)
352+
require.InEpsilon(t, 3700000, metrics.SizeMemoryCache, 0.25)
353353

354354
// Instantiate 4
355355
msg4 := []byte(`{"verifier": "fred", "beneficiary": "jeff"}`)
@@ -368,7 +368,7 @@ func TestGetMetrics(t *testing.T) {
368368
require.Equal(t, uint64(0), metrics.ElementsPinnedMemoryCache)
369369
require.Equal(t, uint64(1), metrics.ElementsMemoryCache)
370370
require.Equal(t, uint64(0), metrics.SizePinnedMemoryCache)
371-
require.InEpsilon(t, 2832576, metrics.SizeMemoryCache, 0.25)
371+
require.InEpsilon(t, 3700000, metrics.SizeMemoryCache, 0.25)
372372
}
373373

374374
func TestLongPayloadDeserialization(t *testing.T) {

0 commit comments

Comments
 (0)