From 43f96a2e886cf73a6a73fad411fc1102de413523 Mon Sep 17 00:00:00 2001 From: lbqds Date: Thu, 20 Jun 2024 22:30:28 +0800 Subject: [PATCH] Fix encoding map key --- .project.json | 16 ++++----- artifacts/test/InsertIntoMap.ral.json | 7 ++-- artifacts/test/MapTest.ral.json | 21 ++++------- artifacts/test/RemoveFromMap.ral.json | 5 +-- artifacts/test/UpdateMapValue.ral.json | 5 +-- artifacts/ts/MapTest.ts | 45 +++++++++++++++++++----- contracts/test/map.ral | 6 +++- docker/docker-compose.yml | 2 +- packages/web3/src/contract/contract.ts | 2 +- packages/web3/src/contract/ralph.test.ts | 11 ++++++ packages/web3/src/contract/ralph.ts | 4 +-- test/contract.test.ts | 15 ++++++-- 12 files changed, 89 insertions(+), 50 deletions(-) diff --git a/.project.json b/.project.json index f3b325437..163135098 100644 --- a/.project.json +++ b/.project.json @@ -1,5 +1,5 @@ { - "fullNodeVersion": "v3.1.0", + "fullNodeVersion": "v3.1.4", "compilerOptionsUsed": { "ignoreUnusedConstantsWarnings": false, "ignoreUnusedVariablesWarnings": false, @@ -193,16 +193,16 @@ }, "InsertIntoMap": { "sourceFile": "test/map.ral", - "sourceCodeHash": "f2f308aaa25fb2bfd984ce7e8f38ba846908a8c0e1a7396244d40e734327b77f", + "sourceCodeHash": "997a7ecabb3c68882a1c28b4889c252258493c1bcb1877d4afe992a872420d38", "bytecodeDebugPatch": "", "codeHashDebug": "", "warnings": [] }, "MapTest": { "sourceFile": "test/map.ral", - "sourceCodeHash": "f2f308aaa25fb2bfd984ce7e8f38ba846908a8c0e1a7396244d40e734327b77f", - "bytecodeDebugPatch": "=6-2+73=2-2+d8=2-2+69=11-1+a=50+7a7e0214696e73657274206174206d617020706174683a2000=56+7a7e0214696e73657274206174206d617020706174683a2000=227-1+9=124+7a7e021472656d6f7665206174206d617020706174683a2000=46+7a7e021472656d6f7665206174206d617020706174683a2000=6", - "codeHashDebug": "034dec32e1107787800ec476a31b11ed2f5c201c06aa9360d1a1a074d6b29098", + "sourceCodeHash": "997a7ecabb3c68882a1c28b4889c252258493c1bcb1877d4afe992a872420d38", + "bytecodeDebugPatch": "=6-2+a8=1-3+128=2-2+ea=10-2+4025=50+7a7e0214696e73657274206174206d617020706174683a2000=56+7a7e0214696e73657274206174206d617020706174683a2000=54+7a7e0214696e73657274206174206d617020706174683a2000=280-2+33=124+7a7e021472656d6f7665206174206d617020706174683a2000=46+7a7e021472656d6f7665206174206d617020706174683a2000=48+7a7e021472656d6f7665206174206d617020706174683a2000=6", + "codeHashDebug": "8666d70738c42748551e987c3eb46a2d7b1db5d82f5f6b2fdfc95b3906ff7477", "warnings": [ "No external caller check for function \"MapTest.remove\". Please use \"checkCaller!(...)\" in the function or its callees, or disable it with \"@using(checkExternalCaller = false)\".", "No external caller check for function \"MapTest.update\". Please use \"checkCaller!(...)\" in the function or its callees, or disable it with \"@using(checkExternalCaller = false)\".", @@ -211,7 +211,7 @@ }, "MapValue": { "sourceFile": "test/map.ral", - "sourceCodeHash": "f2f308aaa25fb2bfd984ce7e8f38ba846908a8c0e1a7396244d40e734327b77f", + "sourceCodeHash": "997a7ecabb3c68882a1c28b4889c252258493c1bcb1877d4afe992a872420d38", "bytecodeDebugPatch": "", "codeHashDebug": "", "warnings": [] @@ -278,7 +278,7 @@ }, "RemoveFromMap": { "sourceFile": "test/map.ral", - "sourceCodeHash": "f2f308aaa25fb2bfd984ce7e8f38ba846908a8c0e1a7396244d40e734327b77f", + "sourceCodeHash": "997a7ecabb3c68882a1c28b4889c252258493c1bcb1877d4afe992a872420d38", "bytecodeDebugPatch": "", "codeHashDebug": "", "warnings": [] @@ -320,7 +320,7 @@ }, "UpdateMapValue": { "sourceFile": "test/map.ral", - "sourceCodeHash": "f2f308aaa25fb2bfd984ce7e8f38ba846908a8c0e1a7396244d40e734327b77f", + "sourceCodeHash": "997a7ecabb3c68882a1c28b4889c252258493c1bcb1877d4afe992a872420d38", "bytecodeDebugPatch": "", "codeHashDebug": "", "warnings": [] diff --git a/artifacts/test/InsertIntoMap.ral.json b/artifacts/test/InsertIntoMap.ral.json index aa9d9ae58..aa0931400 100644 --- a/artifacts/test/InsertIntoMap.ral.json +++ b/artifacts/test/InsertIntoMap.ral.json @@ -1,7 +1,7 @@ { - "version": "v2.14.7", + "version": "v3.1.4", "name": "InsertIntoMap", - "bytecodeTemplate": "01010300020010{2}{3}17011700{1}d10e2ca2{1}160016010f0c{0}0100", + "bytecodeTemplate": "01010300020010{2}{3}17011700{1}d10f2ca2{1}160016010f0c{0}0100", "fieldsSig": { "names": [ "mapTest", @@ -22,9 +22,6 @@ "functions": [ { "name": "main", - "usePreapprovedAssets": true, - "useAssetsInContract": false, - "isPublic": true, "paramNames": [], "paramTypes": [], "paramIsMutable": [], diff --git a/artifacts/test/MapTest.ral.json b/artifacts/test/MapTest.ral.json index fe98914b2..20b1d0952 100644 --- a/artifacts/test/MapTest.ral.json +++ b/artifacts/test/MapTest.ral.json @@ -1,8 +1,8 @@ { - "version": "v2.14.7", + "version": "v3.1.4", "name": "MapTest", - "bytecode": "0003404140a64105010303030016d3a9cdcc691600d1a2140a5f5f6d61705f5f305f5f160047441601b11602d202011600d1a2140a5f5f6d61705f5f315f5f16014044b11602d201010100010400402bd3c50ed2bb0c0d0d140a5f5f6d61705f5f305f5f16004744cb1703160301000c0d0d160301011702170116020d2a0c0e0c140a5f5f6d61705f5f305f5f16004744cb010216020d2a0c0e0c140a5f5f6d61705f5f315f5f16014044cb010201000104004025d392ac08660c0d0d140a5f5f6d61705f5f305f5f16004744cb1703160301000c0d0d160301011702170116000d0c140a5f5f6d61705f5f305f5f16004744cb010316000d0c140a5f5f6d61705f5f315f5f16014044cb0103", - "codeHash": "fa153233f4924fc2fd3e98b43209b838e569154481211662acdade8e20bb48c0", + "bytecode": "0003405c40dc415301030303001fd3a9cdcc691600d1a2140a5f5f6d61705f5f305f5f160047441601b11602d202011600d1a2140a5f5f6d61705f5f315f5f16014044b11602d201011600d1a2140a5f5f6d61705f5f325f5f1402001144b11602d2010101000104004036d3c50ed2bb0c0d0d140a5f5f6d61705f5f305f5f16004744cb1703160301000c0d0d160301011702170116020d2a0c0e0c140a5f5f6d61705f5f305f5f16004744cb010216020d2a0c0e0c140a5f5f6d61705f5f315f5f16014044cb010216020d2a0c0e0c140a5f5f6d61705f5f325f5f1402001144cb01020100010400402dd392ac08660c0d0d140a5f5f6d61705f5f305f5f16004744cb1703160301000c0d0d160301011702170116000d0c140a5f5f6d61705f5f305f5f16004744cb010316000d0c140a5f5f6d61705f5f315f5f16014044cb010316000d0c140a5f5f6d61705f5f325f5f1402001144cb0103", + "codeHash": "6ce8563011315ab1834d01457eb638c0a081c689b0daf1a59f8d914330a8673d", "fieldsSig": { "names": [], "types": [], @@ -12,9 +12,6 @@ "functions": [ { "name": "insert", - "usePreapprovedAssets": true, - "useAssetsInContract": false, - "isPublic": true, "paramNames": [ "key", "value" @@ -31,9 +28,6 @@ }, { "name": "update", - "usePreapprovedAssets": false, - "useAssetsInContract": false, - "isPublic": true, "paramNames": [ "key" ], @@ -47,9 +41,6 @@ }, { "name": "remove", - "usePreapprovedAssets": false, - "useAssetsInContract": false, - "isPublic": true, "paramNames": [ "key" ], @@ -67,11 +58,13 @@ "mapsSig": { "names": [ "map0", - "map1" + "map1", + "map2" ], "types": [ "Map[Address,MapValue]", - "Map[U256,U256]" + "Map[U256,U256]", + "Map[ByteVec,U256]" ] } } \ No newline at end of file diff --git a/artifacts/test/RemoveFromMap.ral.json b/artifacts/test/RemoveFromMap.ral.json index b09474b40..a3f6b5432 100644 --- a/artifacts/test/RemoveFromMap.ral.json +++ b/artifacts/test/RemoveFromMap.ral.json @@ -1,5 +1,5 @@ { - "version": "v2.14.7", + "version": "v3.1.4", "name": "RemoveFromMap", "bytecodeTemplate": "01010300000005{1}0d0c{0}0102", "fieldsSig": { @@ -19,9 +19,6 @@ "functions": [ { "name": "main", - "usePreapprovedAssets": true, - "useAssetsInContract": false, - "isPublic": true, "paramNames": [], "paramTypes": [], "paramIsMutable": [], diff --git a/artifacts/test/UpdateMapValue.ral.json b/artifacts/test/UpdateMapValue.ral.json index d995f5797..c7b86d356 100644 --- a/artifacts/test/UpdateMapValue.ral.json +++ b/artifacts/test/UpdateMapValue.ral.json @@ -1,5 +1,5 @@ { - "version": "v2.14.7", + "version": "v3.1.4", "name": "UpdateMapValue", "bytecodeTemplate": "01010300000005{1}0d0c{0}0101", "fieldsSig": { @@ -19,9 +19,6 @@ "functions": [ { "name": "main", - "usePreapprovedAssets": true, - "useAssetsInContract": false, - "isPublic": true, "paramNames": [], "paramTypes": [], "paramIsMutable": [], diff --git a/artifacts/ts/MapTest.ts b/artifacts/ts/MapTest.ts index ca48afdb6..2d3eeb429 100644 --- a/artifacts/ts/MapTest.ts +++ b/artifacts/ts/MapTest.ts @@ -112,14 +112,22 @@ class Factory extends ContractFactory { TestContractParams< never, { key: Address; value: MapValue }, - { map0?: Map; map1?: Map } + { + map0?: Map; + map1?: Map; + map2?: Map; + } >, "initialFields" > ): Promise< TestContractResult< null, - { map0?: Map; map1?: Map } + { + map0?: Map; + map1?: Map; + map2?: Map; + } > > => { return testMethod(this, "insert", params, getContractByCodeHash); @@ -129,14 +137,22 @@ class Factory extends ContractFactory { TestContractParams< never, { key: Address }, - { map0?: Map; map1?: Map } + { + map0?: Map; + map1?: Map; + map2?: Map; + } >, "initialFields" > ): Promise< TestContractResult< null, - { map0?: Map; map1?: Map } + { + map0?: Map; + map1?: Map; + map2?: Map; + } > > => { return testMethod(this, "update", params, getContractByCodeHash); @@ -146,14 +162,22 @@ class Factory extends ContractFactory { TestContractParams< never, { key: Address }, - { map0?: Map; map1?: Map } + { + map0?: Map; + map1?: Map; + map2?: Map; + } >, "initialFields" > ): Promise< TestContractResult< null, - { map0?: Map; map1?: Map } + { + map0?: Map; + map1?: Map; + map2?: Map; + } > > => { return testMethod(this, "remove", params, getContractByCodeHash); @@ -165,8 +189,8 @@ class Factory extends ContractFactory { export const MapTest = new Factory( Contract.fromJson( MapTestContractJson, - "=6-2+73=2-2+d8=2-2+69=11-1+a=50+7a7e0214696e73657274206174206d617020706174683a2000=56+7a7e0214696e73657274206174206d617020706174683a2000=227-1+9=124+7a7e021472656d6f7665206174206d617020706174683a2000=46+7a7e021472656d6f7665206174206d617020706174683a2000=6", - "034dec32e1107787800ec476a31b11ed2f5c201c06aa9360d1a1a074d6b29098", + "=6-2+a8=1-3+128=2-2+ea=10-2+4025=50+7a7e0214696e73657274206174206d617020706174683a2000=56+7a7e0214696e73657274206174206d617020706174683a2000=54+7a7e0214696e73657274206174206d617020706174683a2000=280-2+33=124+7a7e021472656d6f7665206174206d617020706174683a2000=46+7a7e021472656d6f7665206174206d617020706174683a2000=48+7a7e021472656d6f7665206174206d617020706174683a2000=6", + "8666d70738c42748551e987c3eb46a2d7b1db5d82f5f6b2fdfc95b3906ff7477", AllStructs ) ); @@ -188,6 +212,11 @@ export class MapTestInstance extends ContractInstance { this.contractId, "map1" ), + map2: new RalphMap( + MapTest.contract, + this.contractId, + "map2" + ), }; async fetchState(): Promise { diff --git a/contracts/test/map.ral b/contracts/test/map.ral index e59a80db9..79517233a 100644 --- a/contracts/test/map.ral +++ b/contracts/test/map.ral @@ -5,28 +5,32 @@ struct MapValue { Contract MapTest() { mapping[Address, MapValue] map0 mapping[U256, U256] map1 + mapping[ByteVec, U256] map2 @using(preapprovedAssets = true) pub fn insert(key: Address, value: MapValue) -> () { map0.insert!(key, key, value) map1.insert!(key, value.id, value.balance) + map2.insert!(key, #0011, value.balance) } pub fn update(key: Address) -> () { let value = map0[key] map0[key].balance = value.balance + 1 map1[value.id] = value.balance + 1 + map2[#0011] = value.balance + 1 } pub fn remove(key: Address) -> () { let value = map0[key] map0.remove!(key, key) map1.remove!(key, value.id) + map2.remove!(key, #0011) } } TxScript InsertIntoMap(mapTest: MapTest, from: Address, value: MapValue) { - mapTest.insert{from -> ALPH: mapEntryDeposit!() * 2}(from, value) + mapTest.insert{from -> ALPH: mapEntryDeposit!() * 3}(from, value) } TxScript RemoveFromMap(mapTest: MapTest, key: Address) { diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml index 68b220235..ab2a7aec7 100644 --- a/docker/docker-compose.yml +++ b/docker/docker-compose.yml @@ -31,7 +31,7 @@ services: condition: service_healthy alephium: - image: alephium/alephium:v3.1.0 + image: alephium/alephium:v3.1.4 restart: unless-stopped ports: - 19973:19973/tcp diff --git a/packages/web3/src/contract/contract.ts b/packages/web3/src/contract/contract.ts index af73f7986..e4db6d2d3 100644 --- a/packages/web3/src/contract/contract.ts +++ b/packages/web3/src/contract/contract.ts @@ -1177,7 +1177,7 @@ function calcWrapperContractId( group: number ): string { const prefix = ralph.encodeMapPrefix(mapIndex) - const encodedKey = ralph.primitiveToByteVec(key, keyType) + const encodedKey = ralph.encodeMapKey(key, keyType) const path = binToHex(prefix) + binToHex(encodedKey) return subContractId(parentContractId, path, group) } diff --git a/packages/web3/src/contract/ralph.test.ts b/packages/web3/src/contract/ralph.test.ts index 1ac32f46e..13184f1bd 100644 --- a/packages/web3/src/contract/ralph.test.ts +++ b/packages/web3/src/contract/ralph.test.ts @@ -457,6 +457,17 @@ describe('contract', function () { ) }) + it('should encode map key', () => { + expect(utils.binToHex(ralph.encodeMapKey(true, 'Bool'))).toEqual('01') + expect(utils.binToHex(ralph.encodeMapKey(false, 'Bool'))).toEqual('00') + expect(utils.binToHex(ralph.encodeMapKey(11011n, 'U256'))).toEqual('6b03') + expect(utils.binToHex(ralph.encodeMapKey(11011n, 'I256'))).toEqual('80002b03') + expect(utils.binToHex(ralph.encodeMapKey('1DrDyTr9RpRsQnDnXo2YRiPzPW4ooHX5LLoqXrqfMrpQH', 'Address'))).toEqual( + '00bee85f379545a2ed9f6cceb331288842f378cf0f04012ad4ac8824aae7d6f80a' + ) + expect(utils.binToHex(ralph.encodeMapKey('00112233', 'ByteVec'))).toEqual('00112233') + }) + // it('should test buildByteCode', async () => { // const compiled = { // type: 'TemplateContractByteCode', diff --git a/packages/web3/src/contract/ralph.ts b/packages/web3/src/contract/ralph.ts index f33447e94..c5f570f21 100644 --- a/packages/web3/src/contract/ralph.ts +++ b/packages/web3/src/contract/ralph.ts @@ -389,7 +389,7 @@ export function decodePrimitive(value: Uint8Array, type: string): Val { } } -export function primitiveToByteVec(value: Val, type: string): Uint8Array { +export function encodeMapKey(value: Val, type: string): Uint8Array { switch (type) { case 'Bool': const byte = toApiBoolean(value) ? 1 : 0 @@ -402,7 +402,7 @@ export function primitiveToByteVec(value: Val, type: string): Uint8Array { return encodeU256(BigInt(u256)) case 'ByteVec': const hexStr = toApiByteVec(value) - return encodeByteVec(hexStr) + return hexToBinUnsafe(hexStr) case 'Address': const address = toApiAddress(value) return encodeAddress(address) diff --git a/test/contract.test.ts b/test/contract.test.ts index 3c20ac325..ebc29b4c2 100644 --- a/test/contract.test.ts +++ b/test/contract.test.ts @@ -470,28 +470,33 @@ describe('contract', function () { }) expect(insertResult.maps?.map0?.get(signer.address)).toEqual({ id: 1n, balance: 10n }) expect(insertResult.maps?.map1?.get(1n)).toEqual(10n) + expect(insertResult.maps?.map2?.get('0011')).toEqual(10n) const updateResult = await MapTest.tests.update({ initialMaps: { map0: new Map([[signer.address, { id: 1n, balance: 10n }]]), - map1: new Map([[1n, 10n]]) + map1: new Map([[1n, 10n]]), + map2: new Map([['0011', 10n]]) }, testArgs: { key: signer.address }, inputAssets: [{ address: signer.address, asset: { alphAmount: ONE_ALPH } }] }) expect(updateResult.maps?.map0?.get(signer.address)).toEqual({ id: 1n, balance: 11n }) expect(updateResult.maps?.map1?.get(1n)).toEqual(11n) + expect(updateResult.maps?.map2?.get('0011')).toEqual(11n) const removeResult = await MapTest.tests.remove({ initialMaps: { map0: new Map([[signer.address, { id: 1n, balance: 10n }]]), - map1: new Map([[1n, 10n]]) + map1: new Map([[1n, 10n]]), + map2: new Map([['0011', 10n]]) }, testArgs: { key: signer.address }, inputAssets: [{ address: signer.address, asset: { alphAmount: ONE_ALPH } }] }) expect(removeResult.maps?.map0?.get(signer.address)).toEqual(undefined) expect(removeResult.maps?.map1?.get(1n)).toEqual(undefined) + expect(removeResult.maps?.map2?.get('0011')).toEqual(undefined) }) it('should test map(integration test)', async () => { @@ -516,6 +521,9 @@ describe('contract', function () { expect(await mapTest.maps.map1.contains(0n)).toEqual(false) expect(await mapTest.maps.map1.contains(1n)).toEqual(true) expect(await mapTest.maps.map1.get(1n)).toEqual(10n) + expect(await mapTest.maps.map2.contains('0010')).toEqual(false) + expect(await mapTest.maps.map2.contains('0011')).toEqual(true) + expect(await mapTest.maps.map2.get('0011')).toEqual(10n) await UpdateMapValue.execute(signer, { initialFields: { @@ -526,6 +534,7 @@ describe('contract', function () { expect(await mapTest.maps.map0.get(signer.address)).toEqual({ id: 1n, balance: 11n }) expect(await mapTest.maps.map1.get(1n)).toEqual(11n) + expect(await mapTest.maps.map2.get('0011')).toEqual(11n) await RemoveFromMap.execute(signer, { initialFields: { @@ -538,6 +547,8 @@ describe('contract', function () { expect(await mapTest.maps.map0.get(signer.address)).toEqual(undefined) expect(await mapTest.maps.map1.contains(1n)).toEqual(false) expect(await mapTest.maps.map1.get(1n)).toEqual(undefined) + expect(await mapTest.maps.map2.contains('0011')).toEqual(false) + expect(await mapTest.maps.map2.get('0011')).toEqual(undefined) }) it('should test sign execute method with primitive arguments', async () => {