diff --git a/backend/node/genvm/origin/base_host.py b/backend/node/genvm/origin/base_host.py index 3c93f86b2..68c25f5bc 100644 --- a/backend/node/genvm/origin/base_host.py +++ b/backend/node/genvm/origin/base_host.py @@ -328,7 +328,11 @@ async def wait_all_timeout(): if not coro_loop.done(): coro_loop.cancel() - await coro_loop + + try: + await coro_loop + except Exception as e: + errors.append(e) if not handler.has_result(): if ( diff --git a/backend/protocol_rpc/endpoints.py b/backend/protocol_rpc/endpoints.py index d1500e2e9..2ee187f17 100644 --- a/backend/protocol_rpc/endpoints.py +++ b/backend/protocol_rpc/endpoints.py @@ -1,13 +1,13 @@ # rpc/endpoints.py import random import json +import eth_utils from functools import partial from typing import Any from flask_jsonrpc import JSONRPC from flask_jsonrpc.exceptions import JSONRPCError from sqlalchemy import Table from sqlalchemy.orm import Session - import backend.node.genvm.origin.calldata as genvm_calldata from backend.database_handler.contract_snapshot import ContractSnapshot @@ -36,6 +36,7 @@ decode_signed_transaction, transaction_has_valid_signature, decode_method_call_data, + decode_method_send_data, decode_deployment_data, ) from backend.errors.errors import InvalidAddressError, InvalidTransactionError @@ -331,7 +332,7 @@ async def get_contract_schema( async def get_contract_schema_for_code( - msg_handler: MessageHandler, contract_code: str + msg_handler: MessageHandler, contract_code_hex: str ) -> dict: node = Node( # Mock node just to get the data from the GenVM contract_snapshot=None, @@ -351,7 +352,9 @@ async def get_contract_schema_for_code( msg_handler=msg_handler.with_client_session(get_client_session_id()), contract_snapshot_factory=None, ) - schema = await node.get_contract_schema(contract_code.encode("utf-8")) + schema = await node.get_contract_schema( + eth_utils.hexadecimal.decode_hex(contract_code_hex) + ) return json.loads(schema) @@ -368,7 +371,7 @@ def get_balance( def get_transaction_count( - transactions_processor: TransactionsProcessor, address: str + transactions_processor: TransactionsProcessor, address: str, block: str = "latest" ) -> int: return transactions_processor.get_transaction_count(address) @@ -425,7 +428,7 @@ async def call( raise JSONRPCError( message="running contract failed", data={"receipt": receipt.to_dict()} ) - return base64.b64encode(receipt.result[1:]).decode("ascii") + return eth_utils.hexadecimal.encode_hex(receipt.result[1:]) def send_raw_transaction( @@ -488,7 +491,7 @@ def send_raw_transaction( raise InvalidAddressError( to_address, f"Invalid address to_address: {to_address}" ) - decoded_data = decode_method_call_data(decoded_transaction.data) + decoded_data = decode_method_send_data(decoded_transaction.data) transaction_data = {"calldata": decoded_data.calldata} transaction_type = TransactionType.RUN_CONTRACT leader_only = decoded_data.leader_only diff --git a/backend/protocol_rpc/transactions_parser.py b/backend/protocol_rpc/transactions_parser.py index 2db12b6b0..10642a87e 100644 --- a/backend/protocol_rpc/transactions_parser.py +++ b/backend/protocol_rpc/transactions_parser.py @@ -6,12 +6,14 @@ from eth_account import Account from eth_account._utils.legacy_transactions import Transaction, vrs_from from eth_account._utils.signing import hash_of_signed_transaction +import eth_utils from eth_utils import to_checksum_address from hexbytes import HexBytes from backend.protocol_rpc.types import ( DecodedDeploymentData, DecodedMethodCallData, + DecodedMethodSendData, DecodedTransaction, ) @@ -93,23 +95,27 @@ def transaction_has_valid_signature( return recovered_address == decoded_tx.from_address -def decode_method_call_data(data: str) -> DecodedMethodCallData: +def decode_method_send_data(data: str) -> DecodedMethodSendData: data_bytes = HexBytes(data) try: - data_decoded = rlp.decode(data_bytes, MethodCallTransactionPayload) + data_decoded = rlp.decode(data_bytes, MethodSendTransactionPayload) except rlp.exceptions.DeserializationError as e: print("WARN | falling back to default decode method call data:", e) - data_decoded = rlp.decode(data_bytes, MethodCallTransactionPayloadDefault) + data_decoded = rlp.decode(data_bytes, MethodSendTransactionPayloadDefault) leader_only = getattr(data_decoded, "leader_only", False) - return DecodedMethodCallData( + return DecodedMethodSendData( calldata=data_decoded["calldata"], leader_only=leader_only, ) +def decode_method_call_data(data: str) -> DecodedMethodCallData: + return DecodedMethodCallData(eth_utils.hexadecimal.decode_hex(data)) + + def decode_deployment_data(data: str) -> DecodedDeploymentData: data_bytes = HexBytes(data) @@ -145,14 +151,14 @@ class DeploymentContractTransactionPayloadDefault(rlp.Serializable): ] -class MethodCallTransactionPayload(rlp.Serializable): +class MethodSendTransactionPayload(rlp.Serializable): fields = [ ("calldata", binary), ("leader_only", boolean), ] -class MethodCallTransactionPayloadDefault(rlp.Serializable): +class MethodSendTransactionPayloadDefault(rlp.Serializable): fields = [ ("calldata", binary), ] diff --git a/backend/protocol_rpc/types.py b/backend/protocol_rpc/types.py index 90286c58a..30af5f13d 100644 --- a/backend/protocol_rpc/types.py +++ b/backend/protocol_rpc/types.py @@ -37,6 +37,11 @@ class DecodedTransaction: @dataclass class DecodedMethodCallData: calldata: bytes + + +@dataclass +class DecodedMethodSendData: + calldata: bytes leader_only: bool = False diff --git a/docker/Dockerfile.webrequest b/docker/Dockerfile.webrequest index 9ee8b26d1..144efc345 100644 --- a/docker/Dockerfile.webrequest +++ b/docker/Dockerfile.webrequest @@ -18,11 +18,14 @@ RUN mkdir -p "${base}/${path}" && \ cd "${base}/${selpath}" && \ wget -q https://storage.googleapis.com/chrome-for-testing-public/128.0.6613.119/linux64/chrome-linux64.zip && \ wget -q https://storage.googleapis.com/chrome-for-testing-public/128.0.6613.119/linux64/chromedriver-linux64.zip && \ + unzip chromedriver-linux64.zip && \ + unzip chrome-linux64.zip && \ + rm chromedriver-linux64.zip chrome-linux64.zip && \ wget -q https://github.com/SeleniumHQ/selenium/releases/download/selenium-4.24.0/selenium-server-4.24.0.jar && \ true ENV PYTHONPATH="${base}/${path}" -ENV PATH=":${PATH}" +ENV PATH="${PATH}:${base}:${base}/${selpath}/chromedriver-linux64/:${base}/${selpath}/chrome-linux64/" RUN chown -R appuser:appuser $base USER appuser diff --git a/frontend/package-lock.json b/frontend/package-lock.json index fa1081198..16cd1ee97 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -23,7 +23,7 @@ "defu": "^6.1.4", "dexie": "^4.0.4", "floating-vue": "^5.2.2", - "genlayer-js": "^0.4.6", + "genlayer-js": "^0.6.1", "hash-sum": "^2.0.0", "jump.js": "^1.0.2", "lodash-es": "^4.17.21", @@ -5547,9 +5547,9 @@ } }, "node_modules/genlayer-js": { - "version": "0.4.7", - "resolved": "https://registry.npmjs.org/genlayer-js/-/genlayer-js-0.4.7.tgz", - "integrity": "sha512-vp+7spuVaX7vflZd2q7qmaYgi5Cf7S/h4lAoVhAkFdyAsDStvhtwCdJGcZDt+U77AWxo3I1mUMXz0sk9ER3JXQ==", + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/genlayer-js/-/genlayer-js-0.6.1.tgz", + "integrity": "sha512-1cXIJnlAV9CRcngxRPZfwEvvPIyJmMAnZRca4DarYDGVsaoUhDAopHSJXug/6EcBIg2BLioI9XXvyCeSOz/UvQ==", "dependencies": { "eslint-plugin-import": "^2.30.0", "typescript-parsec": "^0.3.4", diff --git a/frontend/package.json b/frontend/package.json index d453f6c3a..f3fb8d172 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -35,7 +35,7 @@ "defu": "^6.1.4", "dexie": "^4.0.4", "floating-vue": "^5.2.2", - "genlayer-js": "^0.4.6", + "genlayer-js": "^0.6.1", "hash-sum": "^2.0.0", "jump.js": "^1.0.2", "lodash-es": "^4.17.21", diff --git a/frontend/src/calldata/consts.ts b/frontend/src/calldata/consts.ts deleted file mode 100644 index 2f9b6ebb7..000000000 --- a/frontend/src/calldata/consts.ts +++ /dev/null @@ -1,14 +0,0 @@ -export const BITS_IN_TYPE = 3; - -export const TYPE_SPECIAL = 0; -export const TYPE_PINT = 1; -export const TYPE_NINT = 2; -export const TYPE_BYTES = 3; -export const TYPE_STR = 4; -export const TYPE_ARR = 5; -export const TYPE_MAP = 6; - -export const SPECIAL_NULL = (0 << BITS_IN_TYPE) | TYPE_SPECIAL; -export const SPECIAL_FALSE = (1 << BITS_IN_TYPE) | TYPE_SPECIAL; -export const SPECIAL_TRUE = (2 << BITS_IN_TYPE) | TYPE_SPECIAL; -export const SPECIAL_ADDR = (3 << BITS_IN_TYPE) | TYPE_SPECIAL; diff --git a/frontend/src/calldata/decoder.ts b/frontend/src/calldata/decoder.ts deleted file mode 100644 index b3dca9d9a..000000000 --- a/frontend/src/calldata/decoder.ts +++ /dev/null @@ -1,88 +0,0 @@ -import type { CalldataEncodable } from './types'; -import * as consts from './consts'; -import { Address } from './types'; - -function readULeb128(data: Uint8Array, index: { i: number }): bigint { - let res: bigint = 0n; - let accum = 0n; - let shouldContinue = true; - while (shouldContinue) { - const byte = data[index.i]; - index.i++; - const rest = byte & 0x7f; - res += BigInt(rest) * (1n << accum); - accum += 7n; - shouldContinue = byte >= 128; - } - return res; -} - -function decodeImpl(data: Uint8Array, index: { i: number }): CalldataEncodable { - const cur = readULeb128(data, index); - switch (cur) { - case BigInt(consts.SPECIAL_NULL): - return null; - case BigInt(consts.SPECIAL_TRUE): - return true; - case BigInt(consts.SPECIAL_FALSE): - return false; - case BigInt(consts.SPECIAL_ADDR): { - const res = data.slice(index.i, index.i + 20); - index.i += 20; - return new Address(res); - } - } - const type = Number(cur & 0xffn) & ((1 << consts.BITS_IN_TYPE) - 1); - const rest = cur >> BigInt(consts.BITS_IN_TYPE); - switch (type) { - case consts.TYPE_BYTES: { - const ret = data.slice(index.i, index.i + Number(rest)); - index.i += Number(rest); - return ret; - } - case consts.TYPE_PINT: - return rest; - case consts.TYPE_NINT: - return -1n - rest; - case consts.TYPE_STR: { - const ret = data.slice(index.i, index.i + Number(rest)); - index.i += Number(rest); - return new TextDecoder('utf-8').decode(ret); - } - case consts.TYPE_ARR: { - const ret = [] as CalldataEncodable[]; - let elems = rest; - while (elems > 0) { - elems--; - ret.push(decodeImpl(data, index)); - } - return ret; - } - case consts.TYPE_MAP: { - const ret = new Map(); - let elems = rest; - while (elems > 0) { - elems--; - const strLen = Number(readULeb128(data, index)); - const key = data.slice(index.i, index.i + strLen); - index.i += strLen; - const keyStr = new TextDecoder('utf-8').decode(key); - ret.set(keyStr, decodeImpl(data, index)); - } - return ret; - } - default: - throw new Error( - `can't decode type from ${type} rest is ${rest} at pos ${index.i}`, - ); - } -} - -export function decode(data: Uint8Array): CalldataEncodable { - const index = { i: 0 }; - const res = decodeImpl(data, index); - if (index.i !== data.length) { - throw new Error('some data left'); - } - return res; -} diff --git a/frontend/src/calldata/encoder.ts b/frontend/src/calldata/encoder.ts deleted file mode 100644 index 32493a5c8..000000000 --- a/frontend/src/calldata/encoder.ts +++ /dev/null @@ -1,224 +0,0 @@ -import type { CalldataEncodable } from './types'; -import { Address } from './types'; -import * as consts from './consts'; - -function reportError(msg: string, data: CalldataEncodable): never { - throw new Error(`invalid calldata input '${data}'`); -} - -function writeNum(to: number[], data: bigint) { - if (data === 0n) { - to.push(0); - return; - } - while (data > 0) { - let cur = Number(data & 0x7fn); - data >>= 7n; - if (data > 0) { - cur |= 0x80; - } - to.push(cur); - } -} - -function encodeNumWithType(to: number[], data: bigint, type: number) { - const res = (data << BigInt(consts.BITS_IN_TYPE)) | BigInt(type); - writeNum(to, res); -} - -function encodeNum(to: number[], data: bigint) { - if (data >= 0n) { - encodeNumWithType(to, data, consts.TYPE_PINT); - } else { - encodeNumWithType(to, -data - 1n, consts.TYPE_NINT); - } -} - -function compareString(l: number[], r: number[]): number { - for (let index = 0; index < l.length && index < r.length; index++) { - const cur = l[index] - r[index]; - if (cur !== 0) { - return cur; - } - } - return l.length - r.length; -} - -function encodeMap(to: number[], arr: Iterable<[string, CalldataEncodable]>) { - // unicode code points array, utf8 encoded array, item - const newEntries: [number[], Uint8Array, CalldataEncodable][] = Array.from( - arr, - ([k, v]): [number[], Uint8Array, CalldataEncodable] => [ - Array.from(k, (x) => x.codePointAt(0)!), - new TextEncoder().encode(k), - v, - ], - ); - newEntries.sort((v1, v2) => compareString(v1[0], v2[0])); - for (let i = 1; i < newEntries.length; i++) { - if (compareString(newEntries[i - 1][0], newEntries[i][0]) === 0) { - throw new Error( - `duplicate key '${new TextDecoder().decode(newEntries[i][1])}'`, - ); - } - } - - encodeNumWithType(to, BigInt(newEntries.length), consts.TYPE_MAP); - for (const [_k, k, v] of newEntries) { - writeNum(to, BigInt(k.length)); - for (const c of k) { - to.push(c); - } - encodeImpl(to, v); - } -} - -function encodeImpl(to: number[], data: CalldataEncodable) { - if (data === null || data === undefined) { - to.push(consts.SPECIAL_NULL); - return; - } - if (data === true) { - to.push(consts.SPECIAL_TRUE); - return; - } - if (data === false) { - to.push(consts.SPECIAL_FALSE); - return; - } - switch (typeof data) { - case 'number': { - if (!Number.isInteger(data)) { - reportError('floats are not supported', data); - } - encodeNum(to, BigInt(data)); - return; - } - case 'bigint': { - encodeNum(to, data); - return; - } - case 'string': { - const str = new TextEncoder().encode(data); - encodeNumWithType(to, BigInt(str.length), consts.TYPE_STR); - for (const c of str) { - to.push(c); - } - return; - } - case 'object': { - if (data instanceof Uint8Array) { - encodeNumWithType(to, BigInt(data.length), consts.TYPE_BYTES); - for (const c of data) { - to.push(c); - } - } else if (data instanceof Array) { - encodeNumWithType(to, BigInt(data.length), consts.TYPE_ARR); - for (const c of data) { - encodeImpl(to, c); - } - } else if (data instanceof Map) { - encodeMap(to, data); - } else if (data instanceof Address) { - to.push(consts.SPECIAL_ADDR); - for (const c of data.bytes) { - to.push(c); - } - } else if (Object.getPrototypeOf(data) === Object.prototype) { - encodeMap(to, Object.entries(data)); - } else { - reportError('unknown object type', data); - } - return; - } - default: - reportError('unknown base type', data); - } -} - -export function encode(data: CalldataEncodable): Uint8Array { - // FIXME: find a better growable type - const arr: number[] = []; - encodeImpl(arr, data); - return new Uint8Array(arr); -} - -function toStringImplMap( - data: Iterable<[string, CalldataEncodable]>, - to: string[], -) { - to.push('{'); - for (const [k, v] of data) { - to.push(JSON.stringify(k)); - to.push(':'); - toStringImpl(v, to); - } - to.push('}'); -} - -function toStringImpl(data: CalldataEncodable, to: string[]) { - if (data === null || data === undefined) { - to.push('null'); - return; - } - if (data === true) { - to.push('true'); - return; - } - if (data === false) { - to.push('false'); - return; - } - switch (typeof data) { - case 'number': { - if (!Number.isInteger(data)) { - reportError('floats are not supported', data); - } - to.push(data.toString()); - return; - } - case 'bigint': { - to.push(data.toString()); - return; - } - case 'string': { - to.push(JSON.stringify(data)); - return; - } - case 'object': { - if (data instanceof Uint8Array) { - to.push('b#'); - for (const b of data) { - to.push(b.toString(16)); - } - } else if (data instanceof Array) { - to.push('['); - for (const c of data) { - toStringImpl(c, to); - to.push(','); - } - to.push(']'); - } else if (data instanceof Map) { - toStringImplMap(data.entries(), to); - } else if (data instanceof Address) { - to.push('addr#'); - for (const c of data.bytes) { - to.push(c.toString(16)); - } - } else if (Object.getPrototypeOf(data) === Object.prototype) { - toStringImplMap(Object.entries(data), to); - } else { - reportError('unknown object type', data); - } - return; - } - default: - reportError('unknown base type', data); - } -} - -export function toString(data: CalldataEncodable): string { - const to: string[] = []; - toStringImpl(data, to); - return to.join(''); -} diff --git a/frontend/src/calldata/index.ts b/frontend/src/calldata/index.ts deleted file mode 100644 index 195d6f8c9..000000000 --- a/frontend/src/calldata/index.ts +++ /dev/null @@ -1,4 +0,0 @@ -export * from './types'; -export * from './encoder'; -export * from './decoder'; -export * from './parser'; diff --git a/frontend/src/calldata/parser.ts b/frontend/src/calldata/parser.ts index 5954eaf5b..bf6f16c8e 100644 --- a/frontend/src/calldata/parser.ts +++ b/frontend/src/calldata/parser.ts @@ -34,8 +34,7 @@ import { opt, } from 'typescript-parsec'; -import type { CalldataEncodable } from './types'; -import { Address } from './types'; +import { CalldataAddress, type CalldataEncodable } from 'genlayer-js/types'; enum TokenKind { Atom, @@ -172,7 +171,7 @@ TERM.setPattern( apply(tok(TokenKind.Bytes), (v) => parseHex(v.text.substring(2))), apply( tok(TokenKind.Addr), - (v) => new Address(parseHex(v.text.substring(5))), + (v) => new CalldataAddress(parseHex(v.text.substring(5))), ), ), ); diff --git a/frontend/src/calldata/types.ts b/frontend/src/calldata/types.ts deleted file mode 100644 index 1c119ee6e..000000000 --- a/frontend/src/calldata/types.ts +++ /dev/null @@ -1,33 +0,0 @@ -export class Address { - bytes: Uint8Array; - - constructor(addr: Uint8Array) { - if (addr.length != 20) { - throw new Error(`invalid address length ${addr}`); - } - this.bytes = addr; - } -} - -export type CalldataEncodable = - | null - | boolean - | Address - | number - | bigint - | string - | Uint8Array /// bytes - | Address - | Array - | Map - | { [key: string]: CalldataEncodable }; /// also a "map" - -export type MethodDescription = { - method: string; - args: Array; -}; - -export type TransactionData = { - method: string; - args: CalldataEncodable[]; -}; diff --git a/frontend/src/components/Simulator/ContractMethodItem.vue b/frontend/src/components/Simulator/ContractMethodItem.vue index 4e5511fc3..4a84a027a 100644 --- a/frontend/src/components/Simulator/ContractMethodItem.vue +++ b/frontend/src/components/Simulator/ContractMethodItem.vue @@ -7,7 +7,7 @@ import { ChevronDownIcon } from '@heroicons/vue/16/solid'; import { useEventTracking, useContractQueries } from '@/hooks'; import { unfoldArgsData, type ArgData } from './ContractParams'; import ContractParams from './ContractParams.vue'; -import * as calldata from '@/calldata'; +import { abi } from 'genlayer-js'; const { callWriteMethod, callReadMethod, contract } = useContractQueries(); const { trackEvent } = useEventTracking(); @@ -32,18 +32,13 @@ const handleCallReadMethod = async () => { try { const result = await callReadMethod( props.name, - unfoldArgsData({ - args: calldataArguments.value.args, - kwargs: calldataArguments.value.kwargs, - }), + unfoldArgsData(calldataArguments.value), ); - let repr: string; - if (typeof result === 'string') { - const val = Uint8Array.from(atob(result), (c) => c.charCodeAt(0)); - responseMessage.value = calldata.toString(calldata.decode(val)); + if (result !== undefined) { + responseMessage.value = abi.calldata.toString(result); } else { - responseMessage.value = ''; + responseMessage.value = ''; } trackEvent('called_read_method', { diff --git a/frontend/src/components/Simulator/ContractParams.ts b/frontend/src/components/Simulator/ContractParams.ts index 7fc3d4023..b43108b46 100644 --- a/frontend/src/components/Simulator/ContractParams.ts +++ b/frontend/src/components/Simulator/ContractParams.ts @@ -1,8 +1,9 @@ -import * as calldata from '@/calldata'; +import { type CalldataEncodable } from 'genlayer-js/types'; +import { parse as calldataParse } from '@/calldata/parser'; import { AnyFieldValue } from '../global/fields/AnyFieldValue'; export interface SingleArgData { - val: calldata.CalldataEncodable | AnyFieldValue; + val: CalldataEncodable | AnyFieldValue; key: number | string; } @@ -12,13 +13,13 @@ export interface ArgData { } export function unfoldArgsData(args: ArgData): { - args: calldata.CalldataEncodable[]; - kwargs: { [key: string]: calldata.CalldataEncodable }; + args: CalldataEncodable[]; + kwargs: { [key: string]: CalldataEncodable }; } { const unfoldOne = (x: SingleArgData) => { if (x.val instanceof AnyFieldValue) { try { - return calldata.parse(x.val.value); + return calldataParse(x.val.value); } catch (e) { throw new Error(`failed to parse ${x.key}`); } diff --git a/frontend/src/components/Simulator/ContractParams.vue b/frontend/src/components/Simulator/ContractParams.vue index 54562dd74..ee37771b2 100644 --- a/frontend/src/components/Simulator/ContractParams.vue +++ b/frontend/src/components/Simulator/ContractParams.vue @@ -40,7 +40,7 @@ const setInputParams = (method: ContractMethodBase | undefined) => { kwargs: {}, }; let i = 0; - for (const [paramName, paramType] of method.params) { + for (const [_paramName, paramType] of method.params) { newArgs.args.push({ val: getDefaultValueForType(paramType), key: i, diff --git a/frontend/src/components/Simulator/TransactionItem.vue b/frontend/src/components/Simulator/TransactionItem.vue index 3caa8d7e2..d4d0c5aef 100644 --- a/frontend/src/components/Simulator/TransactionItem.vue +++ b/frontend/src/components/Simulator/TransactionItem.vue @@ -10,7 +10,7 @@ import { CheckCircleIcon, XCircleIcon } from '@heroicons/vue/16/solid'; import CopyTextButton from '../global/CopyTextButton.vue'; import { FilterIcon } from 'lucide-vue-next'; import { GavelIcon } from 'lucide-vue-next'; -import * as calldata from '@/calldata'; +import { abi } from 'genlayer-js'; const uiStore = useUIStore(); const nodeStore = useNodeStore(); @@ -76,7 +76,7 @@ function prettifyTxData(x: any): any { k, { status: 'success', - data: calldata.toString(calldata.decode(rest)), + data: abi.calldata.toString(abi.calldata.decode(rest)), }, ]; } else if (val[0] == 1) { diff --git a/frontend/src/hooks/useContractQueries.ts b/frontend/src/hooks/useContractQueries.ts index 0da25e623..874012344 100644 --- a/frontend/src/hooks/useContractQueries.ts +++ b/frontend/src/hooks/useContractQueries.ts @@ -10,11 +10,10 @@ import { useDebounceFn } from '@vueuse/core'; import { notify } from '@kyvg/vue3-notification'; import { useMockContractData } from './useMockContractData'; import { useEventTracking, useGenlayer } from '@/hooks'; -import * as calldata from '@/calldata'; import type { Address, TransactionHash, - ContractSchema, + CalldataEncodable, } from 'genlayer-js/types'; const schema = ref(); @@ -94,8 +93,8 @@ export function useContractQueries() { async function deployContract( args: { - args: calldata.CalldataEncodable[]; - kwargs: { [key: string]: calldata.CalldataEncodable }; + args: CalldataEncodable[]; + kwargs: { [key: string]: CalldataEncodable }; }, leaderOnly: boolean, ) { @@ -178,8 +177,8 @@ export function useContractQueries() { async function callReadMethod( method: string, args: { - args: calldata.CalldataEncodable[]; - kwargs: { [key: string]: calldata.CalldataEncodable }; + args: CalldataEncodable[]; + kwargs: { [key: string]: CalldataEncodable }; }, ) { try { @@ -203,8 +202,8 @@ export function useContractQueries() { }: { method: string; args: { - args: calldata.CalldataEncodable[]; - kwargs: { [key: string]: calldata.CalldataEncodable }; + args: CalldataEncodable[]; + kwargs: { [key: string]: CalldataEncodable }; }; leaderOnly: boolean; }) { diff --git a/frontend/test/unit/calldata/decode.test.ts b/frontend/test/unit/calldata/decode.test.ts index 5728b4544..926c96c54 100644 --- a/frontend/test/unit/calldata/decode.test.ts +++ b/frontend/test/unit/calldata/decode.test.ts @@ -1,6 +1,7 @@ import { describe, it, expect } from 'vitest'; -import * as calldata from '@/calldata'; +import { abi } from 'genlayer-js'; +import { parse as calldataParse } from '@/calldata/parser'; describe('calldata decoding tests', () => { it('smoke', () => { @@ -16,8 +17,8 @@ describe('calldata decoding tests', () => { ); const text = new TextDecoder('utf-8').decode(text_decoded_to_arr); - const parsed = calldata.parse(text); - const decoded = calldata.decode(bin); + const parsed = calldataParse(text); + const decoded = abi.calldata.decode(bin); expect(decoded).toEqual(parsed); }); }); diff --git a/frontend/test/unit/calldata/parse.test.ts b/frontend/test/unit/calldata/parse.test.ts index db2b9f68d..83763844c 100644 --- a/frontend/test/unit/calldata/parse.test.ts +++ b/frontend/test/unit/calldata/parse.test.ts @@ -1,30 +1,32 @@ import { describe, it, expect } from 'vitest'; -import * as calldata from '@/calldata'; +import { abi } from 'genlayer-js'; +import { CalldataAddress } from 'genlayer-js/types'; +import { parse as calldataParse } from '@/calldata/parser'; describe('calldata parsing tests', () => { it('string escapes', () => { - expect(calldata.parse('"\\n"')).toEqual('\n'); - expect(calldata.parse('"\\r"')).toEqual('\r'); - expect(calldata.parse('"\\t"')).toEqual('\t'); - expect(calldata.parse('"\\u00029e3d"')).toEqual('𩸽'); + expect(calldataParse('"\\n"')).toEqual('\n'); + expect(calldataParse('"\\r"')).toEqual('\r'); + expect(calldataParse('"\\t"')).toEqual('\t'); + expect(calldataParse('"\\u00029e3d"')).toEqual('𩸽'); }); it('numbers', () => { - expect(calldata.parse('0')).toEqual(0n); - expect(calldata.parse('0xff')).toEqual(0xffn); - expect(calldata.parse('0o77')).toEqual(0o77n); + expect(calldataParse('0')).toEqual(0n); + expect(calldataParse('0xff')).toEqual(0xffn); + expect(calldataParse('0o77')).toEqual(0o77n); }); it('numbers + sign', () => { - expect(calldata.parse('+0')).toEqual(0n); - expect(calldata.parse('+0xff')).toEqual(0xffn); - expect(calldata.parse('+0o77')).toEqual(0o77n); + expect(calldataParse('+0')).toEqual(0n); + expect(calldataParse('+0xff')).toEqual(0xffn); + expect(calldataParse('+0o77')).toEqual(0o77n); }); it('numbers - sign', () => { - expect(calldata.parse('-0')).toEqual(-0n); - expect(calldata.parse('-0xff')).toEqual(-0xffn); - expect(calldata.parse('-0o77')).toEqual(-0o77n); + expect(calldataParse('-0')).toEqual(-0n); + expect(calldataParse('-0xff')).toEqual(-0xffn); + expect(calldataParse('-0o77')).toEqual(-0o77n); }); it('all types', () => { @@ -47,12 +49,12 @@ describe('calldata parsing tests', () => { str2: 'abc', num: 0xf, bytes: new Uint8Array([0xde, 0xad]), - addr: new calldata.Address(new Uint8Array(new Array(20).map(() => 0))), + addr: new CalldataAddress(new Uint8Array(new Array(20).map(() => 0))), arr: [-2, -0o7, -0xff00, -0], }; - expect(calldata.encode(calldata.parse(asStr))).toEqual( - calldata.encode(asLiteral), + expect(abi.calldata.encode(calldataParse(asStr))).toEqual( + abi.calldata.encode(asLiteral), ); }); @@ -70,22 +72,22 @@ describe('calldata parsing tests', () => { c: [], d: [1], }; - expect(calldata.encode(calldata.parse(asStr))).toEqual( - calldata.encode(asLit), + expect(abi.calldata.encode(calldataParse(asStr))).toEqual( + abi.calldata.encode(asLit), ); }); it('string escapes', () => { - expect(calldata.parse('"\\\\"')).toEqual('\\'); - expect(calldata.parse('"\\n"')).toEqual('\n'); + expect(calldataParse('"\\\\"')).toEqual('\\'); + expect(calldataParse('"\\n"')).toEqual('\n'); - expect(() => calldata.parse('"\\a"')).toThrow(); + expect(() => calldataParse('"\\a"')).toThrow(); }); it('errors', () => { - expect(() => calldata.parse('b#1')).toThrow(); - expect(() => calldata.parse('0xz')).toThrow(); - expect(() => calldata.parse('0o8')).toThrow(); - expect(() => calldata.parse('addr#1234')).toThrow(); + expect(() => calldataParse('b#1')).toThrow(); + expect(() => calldataParse('0xz')).toThrow(); + expect(() => calldataParse('0o8')).toThrow(); + expect(() => calldataParse('addr#1234')).toThrow(); }); }); diff --git a/tests/common/request.py b/tests/common/request.py index 360d111a4..380708dfb 100644 --- a/tests/common/request.py +++ b/tests/common/request.py @@ -1,5 +1,6 @@ # tests/common/request.py import os +import eth_utils import json import requests import time @@ -60,8 +61,8 @@ def call_contract_method( method_name: str, method_args: list, ): - encoded_data = encode_transaction_data( - [calldata.encode({"method": method_name, "args": method_args})] + encoded_data = eth_utils.hexadecimal.encode_hex( + calldata.encode({"method": method_name, "args": method_args}) ) method_response = post_request_localhost( payload( @@ -74,7 +75,7 @@ def call_contract_method( ) ).json() enc_result = method_response["result"] - return calldata.decode(base64.b64decode(enc_result)) + return calldata.decode(eth_utils.hexadecimal.decode_hex(enc_result)) def send_transaction( diff --git a/tests/integration/contract_examples/test_football_prediction_market.py b/tests/integration/contract_examples/test_football_prediction_market.py index f6d88d696..75b044756 100644 --- a/tests/integration/contract_examples/test_football_prediction_market.py +++ b/tests/integration/contract_examples/test_football_prediction_market.py @@ -1,6 +1,6 @@ # tests/e2e/test_storage.py -import json +import eth_utils from tests.common.request import ( deploy_intelligent_contract, @@ -27,7 +27,10 @@ def test_football_prediction_market(setup_validators, from_account): # Get contract schema contract_code = open("examples/contracts/football_prediction_market.py", "r").read() result_schema = post_request_localhost( - payload("gen_getContractSchemaForCode", contract_code) + payload( + "gen_getContractSchemaForCode", + eth_utils.hexadecimal.encode_hex(contract_code), + ) ).json() assert has_success_status(result_schema) assert_dict_exact(result_schema, football_prediction_market_contract_schema) diff --git a/tests/integration/contract_examples/test_llm_erc20.py b/tests/integration/contract_examples/test_llm_erc20.py index f19d27fa0..8c02b2ac7 100644 --- a/tests/integration/contract_examples/test_llm_erc20.py +++ b/tests/integration/contract_examples/test_llm_erc20.py @@ -1,5 +1,6 @@ # tests/e2e/test_storage.py -import json +import eth_utils + from backend.node.types import Address from tests.common.request import ( deploy_intelligent_contract, @@ -35,7 +36,10 @@ def test_llm_erc20(setup_validators): # Get contract schema contract_code = open("examples/contracts/llm_erc20.py", "r").read() result_schema = post_request_localhost( - payload("gen_getContractSchemaForCode", contract_code) + payload( + "gen_getContractSchemaForCode", + eth_utils.hexadecimal.encode_hex(contract_code), + ) ).json() assert has_success_status(result_schema) assert_dict_exact(result_schema, llm_erc20_contract_schema) diff --git a/tests/integration/contract_examples/test_log_indexer.py b/tests/integration/contract_examples/test_log_indexer.py index 0f1c017c7..f41764c5f 100644 --- a/tests/integration/contract_examples/test_log_indexer.py +++ b/tests/integration/contract_examples/test_log_indexer.py @@ -1,4 +1,7 @@ # tests/e2e/test_storage.py + +import eth_utils + from tests.common.request import ( deploy_intelligent_contract, send_transaction, @@ -29,7 +32,10 @@ def test_log_indexer(setup_validators, from_account): # Get contract schema contract_code = open("examples/contracts/log_indexer.py", "r").read() result_schema = post_request_localhost( - payload("gen_getContractSchemaForCode", contract_code) + payload( + "gen_getContractSchemaForCode", + eth_utils.hexadecimal.encode_hex(contract_code), + ) ).json() assert has_success_status(result_schema) assert_dict_exact(result_schema, log_indexer_contract_schema) diff --git a/tests/integration/contract_examples/test_storage.py b/tests/integration/contract_examples/test_storage.py index 27c2049c7..155cdf842 100644 --- a/tests/integration/contract_examples/test_storage.py +++ b/tests/integration/contract_examples/test_storage.py @@ -1,4 +1,7 @@ # tests/e2e/test_storage.py + +import eth_utils + from tests.common.request import ( deploy_intelligent_contract, send_transaction, @@ -30,7 +33,10 @@ def test_storage(setup_validators, from_account): # Get contract schema contract_code = open("examples/contracts/storage.py", "r").read() result_schema = post_request_localhost( - payload("gen_getContractSchemaForCode", contract_code) + payload( + "gen_getContractSchemaForCode", + eth_utils.hexadecimal.encode_hex(contract_code), + ) ).json() assert has_success_status(result_schema) assert_dict_exact(result_schema, storage_contract_schema) diff --git a/tests/integration/contract_examples/test_user_storage.py b/tests/integration/contract_examples/test_user_storage.py index 21d886316..a39a37073 100644 --- a/tests/integration/contract_examples/test_user_storage.py +++ b/tests/integration/contract_examples/test_user_storage.py @@ -1,4 +1,7 @@ # tests/e2e/test_storage.py + +import eth_utils + from tests.common.request import ( deploy_intelligent_contract, send_transaction, @@ -39,7 +42,10 @@ def test_user_storage(setup_validators): # Get contract schema contract_code = open("examples/contracts/user_storage.py", "r").read() result_schema = post_request_localhost( - payload("gen_getContractSchemaForCode", contract_code) + payload( + "gen_getContractSchemaForCode", + eth_utils.hexadecimal.encode_hex(contract_code), + ) ).json() assert has_success_status(result_schema) assert_dict_exact(result_schema, user_storage_contract_schema) diff --git a/tests/integration/contract_examples/test_wizard_of_coin.py b/tests/integration/contract_examples/test_wizard_of_coin.py index 1d96c16d8..f970a5fb1 100644 --- a/tests/integration/contract_examples/test_wizard_of_coin.py +++ b/tests/integration/contract_examples/test_wizard_of_coin.py @@ -1,5 +1,7 @@ # tests/e2e/test_wizard_of_coin.py +import eth_utils + from tests.common.request import ( deploy_intelligent_contract, send_transaction, @@ -24,7 +26,10 @@ def test_wizard_of_coin(setup_validators, from_account): # Get contract schema contract_code = open("examples/contracts/wizard_of_coin.py", "r").read() result_schema = post_request_localhost( - payload("gen_getContractSchemaForCode", contract_code) + payload( + "gen_getContractSchemaForCode", + eth_utils.hexadecimal.encode_hex(contract_code), + ) ).json() assert has_success_status(result_schema) assert_dict_exact(result_schema, wizard_contract_schema) diff --git a/tests/unit/consensus/test_base.py b/tests/unit/consensus/test_base.py index 869db4f8d..581ae735f 100644 --- a/tests/unit/consensus/test_base.py +++ b/tests/unit/consensus/test_base.py @@ -1,6 +1,6 @@ from unittest.mock import Mock -import time import pytest +import asyncio from backend.consensus.base import ( ConsensusAlgorithm, @@ -25,10 +25,17 @@ check_validator_count, get_leader_address, get_validator_addresses, + DEFAULT_FINALITY_WINDOW_SLEEP, DEFAULT_FINALITY_WINDOW, ) +def createConsensusAlgorithm(*args) -> ConsensusAlgorithm: + ret = ConsensusAlgorithm(*args) + ret.set_finality_window_time(DEFAULT_FINALITY_WINDOW) + return ret + + @pytest.mark.asyncio async def test_exec_transaction(managed_thread): """ @@ -69,7 +76,7 @@ def get_vote(): transactions_processor, msg_handler_mock, nodes, node_factory_supplier ) - await ConsensusAlgorithm(None, msg_handler_mock).exec_transaction( + await createConsensusAlgorithm(None, msg_handler_mock).exec_transaction( transaction=transaction, transactions_processor=transactions_processor, snapshot=SnapshotMock(nodes), @@ -83,7 +90,7 @@ def get_vote(): for node in created_nodes: node.exec_transaction.assert_awaited_once_with(transaction) - time.sleep(DEFAULT_FINALITY_WINDOW + 2) + await asyncio.sleep(DEFAULT_FINALITY_WINDOW_SLEEP) assert ( transactions_processor.get_transaction_by_hash(transaction.hash)["status"] @@ -123,7 +130,7 @@ def get_vote(): msg_handler_mock = Mock(MessageHandler) - await ConsensusAlgorithm(None, msg_handler_mock).exec_transaction( + await createConsensusAlgorithm(None, msg_handler_mock).exec_transaction( transaction=transaction, transactions_processor=transactions_processor, snapshot=SnapshotMock(nodes), @@ -210,7 +217,7 @@ def get_vote(): transactions_processor, msg_handler_mock, nodes, node_factory_supplier ) - await ConsensusAlgorithm(None, msg_handler_mock).exec_transaction( + await createConsensusAlgorithm(None, msg_handler_mock).exec_transaction( transaction=transaction, transactions_processor=transactions_processor, snapshot=SnapshotMock(nodes), @@ -219,7 +226,7 @@ def get_vote(): node_factory=node_factory_supplier, ) - time.sleep(DEFAULT_FINALITY_WINDOW + 2) + await asyncio.sleep(DEFAULT_FINALITY_WINDOW_SLEEP) assert transactions_processor.updated_transaction_status_history == { "transaction_hash": [ @@ -301,7 +308,7 @@ def get_vote(): transactions_processor, msg_handler_mock, nodes, node_factory_supplier ) - await ConsensusAlgorithm(None, msg_handler_mock).exec_transaction( + await createConsensusAlgorithm(None, msg_handler_mock).exec_transaction( transaction=transaction, transactions_processor=transactions_processor, snapshot=SnapshotMock(nodes), @@ -326,7 +333,7 @@ def get_vote(): appeal(transaction, transactions_processor) - time.sleep(DEFAULT_FINALITY_WINDOW + 2) + await asyncio.sleep(DEFAULT_FINALITY_WINDOW_SLEEP) assert ( transactions_processor.get_transaction_by_hash(transaction.hash)["status"] @@ -405,7 +412,7 @@ def get_vote(): transactions_processor, msg_handler_mock, nodes, node_factory_supplier ) - await ConsensusAlgorithm(None, msg_handler_mock).exec_transaction( + await createConsensusAlgorithm(None, msg_handler_mock).exec_transaction( transaction=transaction, transactions_processor=transactions_processor, snapshot=SnapshotMock(nodes), @@ -430,7 +437,7 @@ def get_vote(): appeal(transaction, transactions_processor) - time.sleep(DEFAULT_FINALITY_WINDOW + 2) + await asyncio.sleep(DEFAULT_FINALITY_WINDOW_SLEEP) assert ( transactions_processor.get_transaction_by_hash(transaction.hash)["status"] @@ -514,7 +521,7 @@ def get_vote(): transactions_processor, msg_handler_mock, nodes, node_factory_supplier ) - await ConsensusAlgorithm(None, msg_handler_mock).exec_transaction( + await createConsensusAlgorithm(None, msg_handler_mock).exec_transaction( transaction=transaction, transactions_processor=transactions_processor, snapshot=SnapshotMock(nodes), @@ -540,7 +547,7 @@ def get_vote(): appeal(transaction, transactions_processor) - time.sleep(DEFAULT_FINALITY_WINDOW + 2) + await asyncio.sleep(DEFAULT_FINALITY_WINDOW_SLEEP) assert ( transactions_processor.get_transaction_by_hash(transaction.hash)["status"] @@ -572,7 +579,7 @@ def get_vote(): transactions_processor.get_transaction_by_hash(transaction.hash) ) # update the variable with the consensus data - await ConsensusAlgorithm(None, msg_handler_mock).exec_transaction( + await createConsensusAlgorithm(None, msg_handler_mock).exec_transaction( transaction=transaction, transactions_processor=transactions_processor, snapshot=SnapshotMock(nodes), @@ -581,7 +588,7 @@ def get_vote(): node_factory=node_factory_supplier, ) - time.sleep(DEFAULT_FINALITY_WINDOW + 2) + await asyncio.sleep(DEFAULT_FINALITY_WINDOW_SLEEP) assert ( transactions_processor.get_transaction_by_hash(transaction.hash)["status"] @@ -673,7 +680,7 @@ def get_vote(): transactions_processor, msg_handler_mock, nodes, node_factory_supplier ) - await ConsensusAlgorithm(None, msg_handler_mock).exec_transaction( + await createConsensusAlgorithm(None, msg_handler_mock).exec_transaction( transaction=transaction, transactions_processor=transactions_processor, snapshot=SnapshotMock(nodes), @@ -695,7 +702,7 @@ def get_vote(): appeal(transaction, transactions_processor) - time.sleep(DEFAULT_FINALITY_WINDOW + 2) + await asyncio.sleep(DEFAULT_FINALITY_WINDOW_SLEEP) assert ( transactions_processor.get_transaction_by_hash(transaction.hash)["status"] @@ -722,7 +729,7 @@ def get_vote(): transactions_processor.get_transaction_by_hash(transaction.hash) ) # update the variable with the consensus data - await ConsensusAlgorithm(None, msg_handler_mock).exec_transaction( + await createConsensusAlgorithm(None, msg_handler_mock).exec_transaction( transaction=transaction, transactions_processor=transactions_processor, snapshot=SnapshotMock(nodes), @@ -826,7 +833,7 @@ def get_vote(): transactions_processor, msg_handler_mock, nodes, node_factory_supplier ) - await ConsensusAlgorithm(None, msg_handler_mock).exec_transaction( + await createConsensusAlgorithm(None, msg_handler_mock).exec_transaction( transaction=transaction, transactions_processor=transactions_processor, snapshot=SnapshotMock(nodes), @@ -862,7 +869,7 @@ def get_vote(): appeal(transaction, transactions_processor) - time.sleep(DEFAULT_FINALITY_WINDOW + 2) + await asyncio.sleep(DEFAULT_FINALITY_WINDOW_SLEEP) assert ( transactions_processor.get_transaction_by_hash(transaction.hash)["status"] @@ -890,7 +897,7 @@ def get_vote(): transactions_processor.get_transaction_by_hash(transaction.hash) ) # update the variable with the consensus data - await ConsensusAlgorithm(None, msg_handler_mock).exec_transaction( + await createConsensusAlgorithm(None, msg_handler_mock).exec_transaction( transaction=transaction, transactions_processor=transactions_processor, snapshot=SnapshotMock(nodes), @@ -933,7 +940,7 @@ def get_vote(): appeal(transaction, transactions_processor) - time.sleep(DEFAULT_FINALITY_WINDOW + 2) + await asyncio.sleep(DEFAULT_FINALITY_WINDOW_SLEEP) assert ( transactions_processor.get_transaction_by_hash(transaction.hash)["status"] @@ -961,7 +968,7 @@ def get_vote(): transactions_processor.get_transaction_by_hash(transaction.hash) ) # update the variable with the consensus data - await ConsensusAlgorithm(None, msg_handler_mock).exec_transaction( + await createConsensusAlgorithm(None, msg_handler_mock).exec_transaction( transaction=transaction, transactions_processor=transactions_processor, snapshot=SnapshotMock(nodes), @@ -970,7 +977,7 @@ def get_vote(): node_factory=node_factory_supplier, ) - time.sleep(DEFAULT_FINALITY_WINDOW + 2) + await asyncio.sleep(DEFAULT_FINALITY_WINDOW_SLEEP) assert ( transactions_processor.get_transaction_by_hash(transaction.hash)["status"] @@ -1062,7 +1069,7 @@ def get_vote(): transactions_processor, msg_handler_mock, nodes, node_factory_supplier ) - await ConsensusAlgorithm(None, msg_handler_mock).exec_transaction( + await createConsensusAlgorithm(None, msg_handler_mock).exec_transaction( transaction=transaction, transactions_processor=transactions_processor, snapshot=SnapshotMock(nodes), @@ -1106,7 +1113,7 @@ def get_vote(): appeal(transaction, transactions_processor) - time.sleep(1.5) + await asyncio.sleep(1.5) assert ( transactions_processor.get_transaction_by_hash(transaction.hash)["status"] @@ -1153,7 +1160,7 @@ def get_vote(): assert leader_address == get_leader_address(transaction, transactions_processor) assert leader_address not in validator_set_addresses - time.sleep(DEFAULT_FINALITY_WINDOW + 2) + await asyncio.sleep(DEFAULT_FINALITY_WINDOW_SLEEP) assert ( transactions_processor.get_transaction_by_hash(transaction.hash)["status"] @@ -1255,7 +1262,7 @@ def get_vote(): transactions_processor, msg_handler_mock, nodes, node_factory_supplier ) - await ConsensusAlgorithm(None, msg_handler_mock).exec_transaction( + await createConsensusAlgorithm(None, msg_handler_mock).exec_transaction( transaction=transaction, transactions_processor=transactions_processor, snapshot=SnapshotMock(nodes), @@ -1292,7 +1299,7 @@ def get_vote(): appeal(transaction, transactions_processor) - time.sleep(2) + await asyncio.sleep(2) assert ( transactions_processor.get_transaction_by_hash(transaction.hash)["status"] @@ -1320,7 +1327,7 @@ def get_vote(): transactions_processor.get_transaction_by_hash(transaction.hash) ) # update the variable with the consensus data - await ConsensusAlgorithm(None, msg_handler_mock).exec_transaction( + await createConsensusAlgorithm(None, msg_handler_mock).exec_transaction( transaction=transaction, transactions_processor=transactions_processor, snapshot=SnapshotMock(nodes), @@ -1329,7 +1336,7 @@ def get_vote(): node_factory=node_factory_supplier, ) - time.sleep(2) + await asyncio.sleep(2) assert ( transactions_processor.get_transaction_by_hash(transaction.hash)["status"] @@ -1366,7 +1373,7 @@ def get_vote(): # Appeal fails appeal(transaction, transactions_processor) - time.sleep(2) + await asyncio.sleep(2) assert ( transactions_processor.get_transaction_by_hash(transaction.hash)["status"] @@ -1400,7 +1407,7 @@ def get_vote(): # Appeal successful appeal(transaction, transactions_processor) - time.sleep(2) + await asyncio.sleep(2) assert ( transactions_processor.get_transaction_by_hash(transaction.hash)["status"] @@ -1430,7 +1437,7 @@ def get_vote(): transactions_processor.get_transaction_by_hash(transaction.hash) ) # update the variable with the consensus data - await ConsensusAlgorithm(None, msg_handler_mock).exec_transaction( + await createConsensusAlgorithm(None, msg_handler_mock).exec_transaction( transaction=transaction, transactions_processor=transactions_processor, snapshot=SnapshotMock(nodes), @@ -1439,7 +1446,7 @@ def get_vote(): node_factory=node_factory_supplier, ) - time.sleep(DEFAULT_FINALITY_WINDOW + 2) + await asyncio.sleep(DEFAULT_FINALITY_WINDOW_SLEEP) assert ( transactions_processor.get_transaction_by_hash(transaction.hash)["status"] diff --git a/tests/unit/consensus/test_helpers.py b/tests/unit/consensus/test_helpers.py index 84cbd9fa1..f0db22614 100644 --- a/tests/unit/consensus/test_helpers.py +++ b/tests/unit/consensus/test_helpers.py @@ -20,6 +20,7 @@ from backend.protocol_rpc.message_handler.base import MessageHandler DEFAULT_FINALITY_WINDOW = 5 +DEFAULT_FINALITY_WINDOW_SLEEP = DEFAULT_FINALITY_WINDOW * 1.2 + 2 DEFAULT_EXEC_RESULT = b"\x00\x00" # success(null) diff --git a/tests/unit/test_transactions_parser.py b/tests/unit/test_transactions_parser.py index b43223a7e..404299b0f 100644 --- a/tests/unit/test_transactions_parser.py +++ b/tests/unit/test_transactions_parser.py @@ -1,7 +1,7 @@ import pytest from backend.protocol_rpc.transactions_parser import ( - decode_method_call_data, - DecodedMethodCallData, + decode_method_send_data, + DecodedMethodSendData, decode_deployment_data, DecodedDeploymentData, ) @@ -14,14 +14,14 @@ [ ( [{"method": "__init__", "args": ["John Doe"]}, False], - DecodedMethodCallData( + DecodedMethodSendData( calldata=b"\x16\x04args\rDJohn Doe\x06methodD__init__", leader_only=False, ), ), ( [{"method": "__init__", "args": ["John Doe"]}, True], - DecodedMethodCallData( + DecodedMethodSendData( calldata=b"\x16\x04args\rDJohn Doe\x06methodD__init__", leader_only=True, ), @@ -30,16 +30,16 @@ ( [{"method": "__init__", "args": ["John Doe"]}] ), # Should fallback to default - DecodedMethodCallData( + DecodedMethodSendData( calldata=b"\x16\x04args\rDJohn Doe\x06methodD__init__", leader_only=False, ), ), ], ) -def test_decode_method_call_data(data, expected_result): +def test_decode_method_send_data(data, expected_result): encoded = encode([calldata.encode(data[0]), *data[1:]]) - assert decode_method_call_data(encoded) == expected_result + assert decode_method_send_data(encoded) == expected_result @pytest.mark.parametrize(