Skip to content

Commit fd8d253

Browse files
committed
Merge branch 'main' into merge-2.0
2 parents 5307690 + c62cd6e commit fd8d253

File tree

15 files changed

+169
-83
lines changed

15 files changed

+169
-83
lines changed

.github/workflows/lint-go.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ jobs:
2828
# Require: The version of golangci-lint to use.
2929
# When `install-mode` is `binary` (default) the value can be v1.2 or v1.2.3 or `latest` to use the latest version.
3030
# When `install-mode` is `goinstall` the value can be v1.2.3, `latest`, or the hash of a commit.
31-
version: v1.55.2
31+
version: v1.56.2
3232

3333
# Optional: working directory, useful for monorepos
3434
# working-directory: somedir

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,3 +13,6 @@
1313
/demo
1414
tmp
1515
a.out
16+
17+
# macOS
18+
.DS_Store

.golangci.yml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
linters:
2+
# Enable specific linter
3+
# https://golangci-lint.run/usage/linters/#enabled-by-default
4+
enable:
5+
- gofumpt
6+
- goimports
7+
8+
linters-settings:
9+
goimports:
10+
local-prefixes: github.com/CosmWasm/wasmvm

Makefile

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -161,8 +161,11 @@ test-alpine: release-build-alpine create-tester-image
161161
format:
162162
find . -name '*.go' -type f | xargs gofumpt -w -s
163163
find . -name '*.go' -type f | xargs misspell -w
164-
find . -name '*.go' -type f | xargs goimports -w -local github.com/CosmWasm/wasmvm
165164

166165
.PHONY: lint
167166
lint:
168167
golangci-lint run
168+
169+
.PHONY: lint-fix
170+
lint-fix:
171+
golangci-lint run --fix

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ are working on Windows (#288).
108108

109109
Our system currently supports the following builds. In general we can only
110110
support targets that are
111-
[supported by Wasmer's singlepass backend](https://docs.wasmer.io/ecosystem/wasmer/wasmer-features#compiler-support-by-chipset),
111+
[supported by Wasmer's singlepass backend](https://docs.wasmer.io/runtime/features#backend-support-by-chipset),
112112
which for example excludes all 32 bit systems.
113113

114114
<!-- AUTO GENERATED BY libwasmvm_builds.py START -->

docs/MIGRATING.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,10 @@
4545
- `SubMsg` and `Reply` now have a new `Payload` field. This contains arbitrary
4646
bytes from the contract that should be passed through to the corresponding
4747
`Reply` call.
48+
- If you build the statically linked version, you now need to provide
49+
`libwasmvm_muslc.x86_64.a` / `libwasmvm_muslc.aarch64.a` instead of
50+
`libwasmvm_muslc.a`. Previously, you had to rename the downloaded libraries.
51+
This is no longer necessary.
4852

4953
## Renamings
5054

internal/api/bindings.h

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -255,27 +255,34 @@ typedef struct U8SliceView {
255255
uintptr_t len;
256256
} U8SliceView;
257257

258-
typedef struct iterator_t {
258+
/**
259+
* A reference to some tables on the Go side which allow accessing
260+
* the actual iterator instance.
261+
*/
262+
typedef struct IteratorReference {
259263
/**
260264
* An ID assigned to this contract call
261265
*/
262266
uint64_t call_id;
263-
uint64_t iterator_index;
264-
} iterator_t;
267+
/**
268+
* An ID assigned to this iterator
269+
*/
270+
uint64_t iterator_id;
271+
} IteratorReference;
265272

266273
typedef struct IteratorVtable {
267-
int32_t (*next)(struct iterator_t iterator,
274+
int32_t (*next)(struct IteratorReference iterator,
268275
struct gas_meter_t *gas_meter,
269276
uint64_t *gas_used,
270277
struct UnmanagedVector *key_out,
271278
struct UnmanagedVector *value_out,
272279
struct UnmanagedVector *err_msg_out);
273-
int32_t (*next_key)(struct iterator_t iterator,
280+
int32_t (*next_key)(struct IteratorReference iterator,
274281
struct gas_meter_t *gas_meter,
275282
uint64_t *gas_used,
276283
struct UnmanagedVector *key_out,
277284
struct UnmanagedVector *err_msg_out);
278-
int32_t (*next_value)(struct iterator_t iterator,
285+
int32_t (*next_value)(struct IteratorReference iterator,
279286
struct gas_meter_t *gas_meter,
280287
uint64_t *gas_used,
281288
struct UnmanagedVector *value_out,
@@ -284,7 +291,11 @@ typedef struct IteratorVtable {
284291

285292
typedef struct GoIter {
286293
struct gas_meter_t *gas_meter;
287-
struct iterator_t state;
294+
/**
295+
* A reference which identifies the iterator and allows finding and accessing the
296+
* actual iterator instance in Go. Once fully initalized, this is immutable.
297+
*/
298+
struct IteratorReference reference;
288299
struct IteratorVtable vtable;
289300
} GoIter;
290301

internal/api/callbacks.go

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,9 @@ GoError cSet_cgo(db_t *ptr, gas_meter_t *gas_meter, uint64_t *used_gas, U8SliceV
1919
GoError cDelete_cgo(db_t *ptr, gas_meter_t *gas_meter, uint64_t *used_gas, U8SliceView key, UnmanagedVector *errOut);
2020
GoError cScan_cgo(db_t *ptr, gas_meter_t *gas_meter, uint64_t *used_gas, U8SliceView start, U8SliceView end, int32_t order, GoIter *out, UnmanagedVector *errOut);
2121
// iterator
22-
GoError cNext_cgo(iterator_t *ptr, gas_meter_t *gas_meter, uint64_t *used_gas, UnmanagedVector *key, UnmanagedVector *val, UnmanagedVector *errOut);
23-
GoError cNextKey_cgo(iterator_t *ptr, gas_meter_t *gas_meter, uint64_t *used_gas, UnmanagedVector *key, UnmanagedVector *errOut);
24-
GoError cNextValue_cgo(iterator_t *ptr, gas_meter_t *gas_meter, uint64_t *used_gas, UnmanagedVector *val, UnmanagedVector *errOut);
22+
GoError cNext_cgo(IteratorReference *ref, gas_meter_t *gas_meter, uint64_t *used_gas, UnmanagedVector *key, UnmanagedVector *val, UnmanagedVector *errOut);
23+
GoError cNextKey_cgo(IteratorReference *ref, gas_meter_t *gas_meter, uint64_t *used_gas, UnmanagedVector *key, UnmanagedVector *errOut);
24+
GoError cNextValue_cgo(IteratorReference *ref, gas_meter_t *gas_meter, uint64_t *used_gas, UnmanagedVector *val, UnmanagedVector *errOut);
2525
// api
2626
GoError cHumanizeAddress_cgo(api_t *ptr, U8SliceView src, UnmanagedVector *dest, UnmanagedVector *errOut, uint64_t *used_gas);
2727
GoError cCanonicalizeAddress_cgo(api_t *ptr, U8SliceView src, UnmanagedVector *dest, UnmanagedVector *errOut, uint64_t *used_gas);
@@ -138,14 +138,14 @@ const frameLenLimit = 32768
138138

139139
// contract: original pointer/struct referenced must live longer than C.Db struct
140140
// since this is only used internally, we can verify the code that this is the case
141-
func buildIterator(callID uint64, it types.Iterator) (C.iterator_t, error) {
142-
idx, err := storeIterator(callID, it, frameLenLimit)
141+
func buildIterator(callID uint64, it types.Iterator) (C.IteratorReference, error) {
142+
iteratorID, err := storeIterator(callID, it, frameLenLimit)
143143
if err != nil {
144-
return C.iterator_t{}, err
144+
return C.IteratorReference{}, err
145145
}
146-
return C.iterator_t{
147-
call_id: cu64(callID),
148-
iterator_index: cu64(idx),
146+
return C.IteratorReference{
147+
call_id: cu64(callID),
148+
iterator_id: cu64(iteratorID),
149149
}, nil
150150
}
151151

@@ -257,7 +257,7 @@ func cScan(ptr *C.db_t, gasMeter *C.gas_meter_t, usedGas *cu64, start C.U8SliceV
257257
gasAfter := gm.GasConsumed()
258258
*usedGas = (cu64)(gasAfter - gasBefore)
259259

260-
cIterator, err := buildIterator(state.CallID, iter)
260+
iteratorRef, err := buildIterator(state.CallID, iter)
261261
if err != nil {
262262
// store the actual error message in the return buffer
263263
*errOut = newUnmanagedVector([]byte(err.Error()))
@@ -266,15 +266,15 @@ func cScan(ptr *C.db_t, gasMeter *C.gas_meter_t, usedGas *cu64, start C.U8SliceV
266266

267267
*out = C.GoIter{
268268
gas_meter: gasMeter,
269-
state: cIterator,
269+
reference: iteratorRef,
270270
vtable: iterator_vtable,
271271
}
272272

273273
return C.GoError_None
274274
}
275275

276276
//export cNext
277-
func cNext(ref C.iterator_t, gasMeter *C.gas_meter_t, usedGas *cu64, key *C.UnmanagedVector, val *C.UnmanagedVector, errOut *C.UnmanagedVector) (ret C.GoError) {
277+
func cNext(ref C.IteratorReference, gasMeter *C.gas_meter_t, usedGas *cu64, key *C.UnmanagedVector, val *C.UnmanagedVector, errOut *C.UnmanagedVector) (ret C.GoError) {
278278
// typical usage of iterator
279279
// for ; itr.Valid(); itr.Next() {
280280
// k, v := itr.Key(); itr.Value()
@@ -291,7 +291,7 @@ func cNext(ref C.iterator_t, gasMeter *C.gas_meter_t, usedGas *cu64, key *C.Unma
291291
}
292292

293293
gm := *(*types.GasMeter)(unsafe.Pointer(gasMeter))
294-
iter := retrieveIterator(uint64(ref.call_id), uint64(ref.iterator_index))
294+
iter := retrieveIterator(uint64(ref.call_id), uint64(ref.iterator_id))
295295
if iter == nil {
296296
panic("Unable to retrieve iterator.")
297297
}
@@ -315,17 +315,17 @@ func cNext(ref C.iterator_t, gasMeter *C.gas_meter_t, usedGas *cu64, key *C.Unma
315315
}
316316

317317
//export cNextKey
318-
func cNextKey(ref C.iterator_t, gasMeter *C.gas_meter_t, usedGas *cu64, key *C.UnmanagedVector, errOut *C.UnmanagedVector) (ret C.GoError) {
318+
func cNextKey(ref C.IteratorReference, gasMeter *C.gas_meter_t, usedGas *cu64, key *C.UnmanagedVector, errOut *C.UnmanagedVector) (ret C.GoError) {
319319
return nextPart(ref, gasMeter, usedGas, key, errOut, func(iter types.Iterator) []byte { return iter.Key() })
320320
}
321321

322322
//export cNextValue
323-
func cNextValue(ref C.iterator_t, gasMeter *C.gas_meter_t, usedGas *cu64, value *C.UnmanagedVector, errOut *C.UnmanagedVector) (ret C.GoError) {
323+
func cNextValue(ref C.IteratorReference, gasMeter *C.gas_meter_t, usedGas *cu64, value *C.UnmanagedVector, errOut *C.UnmanagedVector) (ret C.GoError) {
324324
return nextPart(ref, gasMeter, usedGas, value, errOut, func(iter types.Iterator) []byte { return iter.Value() })
325325
}
326326

327327
// nextPart is a helper function that contains the shared code for key- and value-only iteration.
328-
func nextPart(ref C.iterator_t, gasMeter *C.gas_meter_t, usedGas *cu64, output *C.UnmanagedVector, errOut *C.UnmanagedVector, valFn func(types.Iterator) []byte) (ret C.GoError) {
328+
func nextPart(ref C.IteratorReference, gasMeter *C.gas_meter_t, usedGas *cu64, output *C.UnmanagedVector, errOut *C.UnmanagedVector, valFn func(types.Iterator) []byte) (ret C.GoError) {
329329
// typical usage of iterator
330330
// for ; itr.Valid(); itr.Next() {
331331
// k, v := itr.Key(); itr.Value()
@@ -342,7 +342,7 @@ func nextPart(ref C.iterator_t, gasMeter *C.gas_meter_t, usedGas *cu64, output *
342342
}
343343

344344
gm := *(*types.GasMeter)(unsafe.Pointer(gasMeter))
345-
iter := retrieveIterator(uint64(ref.call_id), uint64(ref.iterator_index))
345+
iter := retrieveIterator(uint64(ref.call_id), uint64(ref.iterator_id))
346346
if iter == nil {
347347
panic("Unable to retrieve iterator.")
348348
}

internal/api/callbacks_cgo.go

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,9 @@ GoError cGet(db_t *ptr, gas_meter_t *gas_meter, uint64_t *used_gas, U8SliceView
1010
GoError cDelete(db_t *ptr, gas_meter_t *gas_meter, uint64_t *used_gas, U8SliceView key, UnmanagedVector *errOut);
1111
GoError cScan(db_t *ptr, gas_meter_t *gas_meter, uint64_t *used_gas, U8SliceView start, U8SliceView end, int32_t order, GoIter *out, UnmanagedVector *errOut);
1212
// imports (iterator)
13-
GoError cNext(iterator_t *ptr, gas_meter_t *gas_meter, uint64_t *used_gas, UnmanagedVector *key, UnmanagedVector *val, UnmanagedVector *errOut);
14-
GoError cNextKey(iterator_t *ptr, gas_meter_t *gas_meter, uint64_t *used_gas, UnmanagedVector *key, UnmanagedVector *errOut);
15-
GoError cNextValue(iterator_t *ptr, gas_meter_t *gas_meter, uint64_t *used_gas, UnmanagedVector *value, UnmanagedVector *errOut);
13+
GoError cNext(IteratorReference *ref, gas_meter_t *gas_meter, uint64_t *used_gas, UnmanagedVector *key, UnmanagedVector *val, UnmanagedVector *errOut);
14+
GoError cNextKey(IteratorReference *ref, gas_meter_t *gas_meter, uint64_t *used_gas, UnmanagedVector *key, UnmanagedVector *errOut);
15+
GoError cNextValue(IteratorReference *ref, gas_meter_t *gas_meter, uint64_t *used_gas, UnmanagedVector *value, UnmanagedVector *errOut);
1616
// imports (api)
1717
GoError cHumanizeAddress(api_t *ptr, U8SliceView src, UnmanagedVector *dest, UnmanagedVector *errOut, uint64_t *used_gas);
1818
GoError cCanonicalizeAddress(api_t *ptr, U8SliceView src, UnmanagedVector *dest, UnmanagedVector *errOut, uint64_t *used_gas);
@@ -35,14 +35,14 @@ GoError cScan_cgo(db_t *ptr, gas_meter_t *gas_meter, uint64_t *used_gas, U8Slice
3535
}
3636
3737
// Gateway functions (iterator)
38-
GoError cNext_cgo(iterator_t *ptr, gas_meter_t *gas_meter, uint64_t *used_gas, UnmanagedVector *key, UnmanagedVector *val, UnmanagedVector *errOut) {
39-
return cNext(ptr, gas_meter, used_gas, key, val, errOut);
38+
GoError cNext_cgo(IteratorReference *ref, gas_meter_t *gas_meter, uint64_t *used_gas, UnmanagedVector *key, UnmanagedVector *val, UnmanagedVector *errOut) {
39+
return cNext(ref, gas_meter, used_gas, key, val, errOut);
4040
}
41-
GoError cNextKey_cgo(iterator_t *ptr, gas_meter_t *gas_meter, uint64_t *used_gas, UnmanagedVector *key, UnmanagedVector *errOut) {
42-
return cNextKey(ptr, gas_meter, used_gas, key, errOut);
41+
GoError cNextKey_cgo(IteratorReference *ref, gas_meter_t *gas_meter, uint64_t *used_gas, UnmanagedVector *key, UnmanagedVector *errOut) {
42+
return cNextKey(ref, gas_meter, used_gas, key, errOut);
4343
}
44-
GoError cNextValue_cgo(iterator_t *ptr, gas_meter_t *gas_meter, uint64_t *used_gas, UnmanagedVector *val, UnmanagedVector *errOut) {
45-
return cNextValue(ptr, gas_meter, used_gas, val, errOut);
44+
GoError cNextValue_cgo(IteratorReference *ref, gas_meter_t *gas_meter, uint64_t *used_gas, UnmanagedVector *val, UnmanagedVector *errOut) {
45+
return cNextValue(ref, gas_meter, used_gas, val, errOut);
4646
}
4747
4848
// Gateway functions (api)

internal/api/iterator.go

Lines changed: 48 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package api
22

33
import (
44
"fmt"
5+
"math"
56
"sync"
67

78
"github.com/CosmWasm/wasmvm/v2/types"
@@ -53,39 +54,71 @@ func endCall(callID uint64) {
5354
}
5455
}
5556

56-
// storeIterator will add this to the end of the frame for the given ID and return a reference to it.
57-
// We start counting with 1, so the 0 value is flagged as an error. This means we must
58-
// remember to do idx-1 when retrieving
57+
// storeIterator will add this to the end of the frame for the given call ID and return
58+
// an iterator ID to reference it.
59+
//
60+
// We assign iterator IDs starting with 1 for historic reasons. This could be changed to 0
61+
// I guess.
5962
func storeIterator(callID uint64, it types.Iterator, frameLenLimit int) (uint64, error) {
6063
iteratorFramesMutex.Lock()
6164
defer iteratorFramesMutex.Unlock()
6265

63-
old_frame_len := len(iteratorFrames[callID])
64-
if old_frame_len >= frameLenLimit {
66+
new_index := len(iteratorFrames[callID])
67+
if new_index >= frameLenLimit {
6568
return 0, fmt.Errorf("Reached iterator limit (%d)", frameLenLimit)
6669
}
6770

68-
// store at array position `old_frame_len`
71+
// store at array position `new_index`
6972
iteratorFrames[callID] = append(iteratorFrames[callID], it)
70-
new_index := old_frame_len + 1
7173

72-
return uint64(new_index), nil
74+
iterator_id, ok := indexToIteratorID(new_index)
75+
if !ok {
76+
// This error case is not expected to happen since the above code ensures the
77+
// index is in the range [0, frameLenLimit-1]
78+
return 0, fmt.Errorf("could not convert index to iterator ID")
79+
}
80+
return iterator_id, nil
7381
}
7482

75-
// retrieveIterator will recover an iterator based on index. This ensures it will not be garbage collected.
76-
// We start counting with 1, in storeIterator so the 0 value is flagged as an error. This means we must
77-
// remember to do idx-1 when retrieving
78-
func retrieveIterator(callID uint64, index uint64) types.Iterator {
83+
// retrieveIterator will recover an iterator based on its ID.
84+
func retrieveIterator(callID uint64, iteratorID uint64) types.Iterator {
85+
indexInFrame, ok := iteratorIdToIndex(iteratorID)
86+
if !ok {
87+
return nil
88+
}
89+
7990
iteratorFramesMutex.Lock()
8091
defer iteratorFramesMutex.Unlock()
8192
myFrame := iteratorFrames[callID]
8293
if myFrame == nil {
8394
return nil
8495
}
85-
posInFrame := int(index) - 1
86-
if posInFrame < 0 || posInFrame >= len(myFrame) {
96+
if indexInFrame >= len(myFrame) {
8797
// index out of range
8898
return nil
8999
}
90-
return myFrame[posInFrame]
100+
return myFrame[indexInFrame]
101+
}
102+
103+
// iteratorIdToIndex converts an iterator ID to an index in the frame.
104+
// The second value marks if the conversion succeeded.
105+
func iteratorIdToIndex(id uint64) (int, bool) {
106+
if id < 1 || id > math.MaxInt32 {
107+
// If success is false, the int value is undefined. We use an arbitrary constant for potential debugging purposes.
108+
return 777777777, false
109+
}
110+
111+
// Int conversion safe because value is in signed 32bit integer range
112+
return int(id) - 1, true
113+
}
114+
115+
// indexToIteratorID converts an index in the frame to an iterator ID.
116+
// The second value marks if the conversion succeeded.
117+
func indexToIteratorID(index int) (uint64, bool) {
118+
if index < 0 || index > math.MaxInt32 {
119+
// If success is false, the return value is undefined. We use an arbitrary constant for potential debugging purposes.
120+
return 888888888, false
121+
}
122+
123+
return uint64(index) + 1, true
91124
}

0 commit comments

Comments
 (0)