From 7a2587593ce1ae5166b86d2ab025900ee6b09a5b Mon Sep 17 00:00:00 2001 From: Virgil Date: Thu, 7 Nov 2024 16:16:09 +0200 Subject: [PATCH 01/10] String encoding for return values --- rust-semantics/error.md | 5 + tests/ulm-contracts/bytes_hooks.rs | 3 + tests/ulm-contracts/test_helpers.rs | 12 + tests/ulm-with-contract/types.rs | 15 + tests/ulm-with-contract/types.str.run | 17 + ulm-semantics/main/encoding/encoder.md | 294 ++++++++++++++++-- ulm-semantics/main/encoding/syntax.md | 8 +- ulm-semantics/main/hooks/bytes.md | 15 + ulm-semantics/main/preprocessing/endpoints.md | 27 +- ulm-semantics/main/preprocessing/events.md | 43 ++- ulm-semantics/main/preprocessing/syntax.md | 2 +- 11 files changed, 387 insertions(+), 54 deletions(-) create mode 100644 tests/ulm-with-contract/types.rs create mode 100644 tests/ulm-with-contract/types.str.run diff --git a/rust-semantics/error.md b/rust-semantics/error.md index 96ae8365..5c7b59b0 100644 --- a/rust-semantics/error.md +++ b/rust-semantics/error.md @@ -12,6 +12,7 @@ module RUST-ERROR-SYNTAX syntax TypePathOrError ::= injectOrError(TypePathSegmentsOrError) [function, total] syntax TypePathSegmentsOrError ::= concat(TypePathSegment, TypePathSegmentsOrError) [function, total] syntax ExpressionOrError ::= andOrError(ExpressionOrError, ExpressionOrError) [function, total] + syntax ExpressionOrError ::= addOrError(ExpressionOrError, ExpressionOrError) [function, total] syntax ValueOrError ::= tupleOrError(ValueListOrError) [function, total] endmodule @@ -52,6 +53,10 @@ module RUST-ERROR rule andOrError(e(E:SemanticsError), v(_:Expression)) => e(E) rule andOrError(v(E1:Expression), v(E2:Expression)) => v(E1 && E2) + rule addOrError(_:ExpressionOrError, e(E:SemanticsError)) => e(E) + rule addOrError(e(E:SemanticsError), v(_:Expression)) => e(E) + rule addOrError(v(E1:Expression), v(E2:Expression)) => v(E1 + E2) + rule tupleOrError(L:ValueList) => tuple(L) rule tupleOrError(E:SemanticsError) => E endmodule diff --git a/tests/ulm-contracts/bytes_hooks.rs b/tests/ulm-contracts/bytes_hooks.rs index 74c8a43b..9ec9a902 100644 --- a/tests/ulm-contracts/bytes_hooks.rs +++ b/tests/ulm-contracts/bytes_hooks.rs @@ -13,6 +13,8 @@ extern "C" { fn append_bool(bytes_id: u64, value: bool) -> u64; fn append_str(bytes_id: u64, value: &str) -> u64; + fn append_bytes_raw(bytes_id: u64, to_append: u64) -> u64; + fn decode_u256(bytes_id: u64) -> (u64, u256); fn decode_u160(bytes_id: u64) -> (u64, u160); fn decode_u128(bytes_id: u64) -> (u64, u128); @@ -20,6 +22,7 @@ extern "C" { fn decode_u32(bytes_id: u64) -> (u64, u32); fn decode_u16(bytes_id: u64) -> (u64, u16); fn decode_u8(bytes_id: u64) -> (u64, u8); + fn decode_str(bytes_id: u64) -> (u64, str); fn decode_signature(bytes_id: u64) -> (u64, u64); fn hash(bytes_id: u64) -> u256; diff --git a/tests/ulm-contracts/test_helpers.rs b/tests/ulm-contracts/test_helpers.rs index 5d7ba179..10785bfd 100644 --- a/tests/ulm-contracts/test_helpers.rs +++ b/tests/ulm-contracts/test_helpers.rs @@ -14,3 +14,15 @@ fn decode_single_u256(bytes_id: u64) -> u256 { }; value } + +fn decode_single_str(bytes_id: u64) -> str { + let (remaining_id, prefix_size) = :: bytes_hooks :: decode_u256(bytes_id); + if prefix_size != 32_u256 { + fail(); + }; + let (remaining_id, value) = :: bytes_hooks :: decode_str(remaining_id); + if :: bytes_hooks :: length(remaining_id) > 0_u32 { + fail(); + }; + value +} diff --git a/tests/ulm-with-contract/types.rs b/tests/ulm-with-contract/types.rs new file mode 100644 index 00000000..b0963fe7 --- /dev/null +++ b/tests/ulm-with-contract/types.rs @@ -0,0 +1,15 @@ +#![no_std] + +#[allow(unused_imports)] +use ulm::*; + +#[ulm::contract] +pub trait Types { + #[init] + fn init(&self) {} + + #[endpoint(strEndpoint)] + fn str_endpoint(&self) -> str { + "Hello" + } +} diff --git a/tests/ulm-with-contract/types.str.run b/tests/ulm-with-contract/types.str.run new file mode 100644 index 00000000..efc2c17d --- /dev/null +++ b/tests/ulm-with-contract/types.str.run @@ -0,0 +1,17 @@ +push "strEndpoint"; +hold_string_from_test_stack; +hold_list_values_from_test_stack; +hold_list_values_from_test_stack; +encode_call_data; + +return_value; +mock CallData; + +call_contract 12345; +return_value; +check_eq (); + +push_status; +check_eq 2; +output_to_arg; call :: test_helpers :: decode_single_str; return_value; +check_eq "Hello" diff --git a/ulm-semantics/main/encoding/encoder.md b/ulm-semantics/main/encoding/encoder.md index f769b9ce..7c075c52 100644 --- a/ulm-semantics/main/encoding/encoder.md +++ b/ulm-semantics/main/encoding/encoder.md @@ -59,6 +59,7 @@ module ULM-CALLDATA-ENCODER imports private ULM-ENCODING-HELPER syntax Identifier ::= "bytes_hooks" [token] + | "append_bytes_raw" [token] | "append_u8" [token] | "append_u16" [token] | "append_u32" [token] @@ -67,6 +68,9 @@ module ULM-CALLDATA-ENCODER | "append_u160" [token] | "append_u256" [token] | "append_bool" [token] + | "append_str" [token] + | "empty" [token] + | "length" [token] rule encodeFunctionSignatureAsBytes(FS) @@ -105,25 +109,269 @@ module ULM-CALLDATA-ENCODER rule encodeFunctionParams(.List, .List, B:Bytes) => B - rule appendValue(BufferId:Identifier, Value:Identifier, u8) - => v(:: bytes_hooks :: append_u8 ( BufferId , Value , .CallParamsList )) - rule appendValue(BufferId:Identifier, Value:Identifier, u16) - => v(:: bytes_hooks :: append_u16 ( BufferId , Value , .CallParamsList )) - rule appendValue(BufferId:Identifier, Value:Identifier, u32) - => v(:: bytes_hooks :: append_u32 ( BufferId , Value , .CallParamsList )) - rule appendValue(BufferId:Identifier, Value:Identifier, u64) - => v(:: bytes_hooks :: append_u64 ( BufferId , Value , .CallParamsList )) - rule appendValue(BufferId:Identifier, Value:Identifier, u128) - => v(:: bytes_hooks :: append_u128 ( BufferId , Value , .CallParamsList )) - rule appendValue(BufferId:Identifier, Value:Identifier, u160) - => v(:: bytes_hooks :: append_u160 ( BufferId , Value , .CallParamsList )) - rule appendValue(BufferId:Identifier, Value:Identifier, u256) - => v(:: bytes_hooks :: append_u256 ( BufferId , Value , .CallParamsList )) - rule appendValue(BufferId:Identifier, Value:Identifier, bool) - => v(:: bytes_hooks :: append_bool ( BufferId , Value , .CallParamsList )) - rule appendValue(BufferId:Identifier, _Value:Identifier, ()) => v(BufferId) - rule appendValue(BufferId:Identifier, Value:Identifier, T:Type) - => e(error("appendValue: unrecognized type", ListItem(BufferId) ListItem(Value) ListItem(T))) + // rule appendValue(BufferId:Identifier, Value:Identifier, u8) + // => v(:: bytes_hooks :: append_u8 ( BufferId , Value , .CallParamsList )) + // rule appendValue(BufferId:Identifier, Value:Identifier, u16) + // => v(:: bytes_hooks :: append_u16 ( BufferId , Value , .CallParamsList )) + // rule appendValue(BufferId:Identifier, Value:Identifier, u32) + // => v(:: bytes_hooks :: append_u32 ( BufferId , Value , .CallParamsList )) + // rule appendValue(BufferId:Identifier, Value:Identifier, u64) + // => v(:: bytes_hooks :: append_u64 ( BufferId , Value , .CallParamsList )) + // rule appendValue(BufferId:Identifier, Value:Identifier, u128) + // => v(:: bytes_hooks :: append_u128 ( BufferId , Value , .CallParamsList )) + // rule appendValue(BufferId:Identifier, Value:Identifier, u160) + // => v(:: bytes_hooks :: append_u160 ( BufferId , Value , .CallParamsList )) + // rule appendValue(BufferId:Identifier, Value:Identifier, u256) + // => v(:: bytes_hooks :: append_u256 ( BufferId , Value , .CallParamsList )) + // rule appendValue(BufferId:Identifier, Value:Identifier, bool) + // => v(:: bytes_hooks :: append_bool ( BufferId , Value , .CallParamsList )) + // rule appendValue(BufferId:Identifier, _Value:Identifier, ()) => v(BufferId) + // rule appendValue(BufferId:Identifier, Value:Identifier, T:Type) + // => e(error("appendValue: unrecognized type", ListItem(BufferId) ListItem(Value) ListItem(T))) + // [owise] + + syntax Identifier ::= "ulm#head_size" [token] + | "ulm#head" [token] + | "ulm#tail" [token] + + syntax NonEmptyStatementsOrError ::= #encodeStatements + ( bufferId: Identifier + , headSize: ExpressionOrError + , append: NonEmptyStatementsOrError + ) [function, total] + + rule encodeStatements(... bufferId: BufferId:Identifier, values: Values:EncodeValues) + => #encodeStatements(BufferId, totalHeadSize(Values), appendValues(Values, ulm#head_size, ulm#head, ulm#tail)) + + rule #encodeStatements(_BufferId:Identifier, e(HeadSize:SemanticsError), _AppendValues:NonEmptyStatementsOrError) + => HeadSize + rule #encodeStatements(_BufferId:Identifier, v(_HeadSize:Expression), AppendValues:SemanticsError) + => AppendValues + rule #encodeStatements(BufferId:Identifier, v(HeadSize:Expression), AppendValues:NonEmptyStatements) + => concatNonEmptyStatements + ( let ulm#head_size = HeadSize; + let ulm#head = :: bytes_hooks :: empty ( .CallParamsList ); + let ulm#tail = :: bytes_hooks :: empty ( .CallParamsList ); + AppendValues + , let BufferId = :: bytes_hooks :: append_bytes_raw ( BufferId, ulm#head , .CallParamsList); + let BufferId = :: bytes_hooks :: append_bytes_raw ( BufferId, ulm#tail , .CallParamsList); + .NonEmptyStatements + ) + + syntax ExpressionOrError ::= totalHeadSize(EncodeValues) [function, total] + rule totalHeadSize(.EncodeValues) => v(ptrValue(null, u32(0p32))) + rule totalHeadSize(_:Expression : T:Type , Evs:EncodeValues) + => addOrError(headSize(T), totalHeadSize(Evs)) + + syntax NonEmptyStatementsOrError ::= appendValues + ( values: EncodeValues + , headSize: Expression + , head: Expression + , tail: Expression + ) [function, total] + rule appendValues(.EncodeValues, _HeadSize:Expression, _Head:Expression, _Tail:Expression) + => .NonEmptyStatements + rule appendValues + ( V:Expression : T:Type , Evs:EncodeValues + , HeadSize:Expression + , Head:Expression + , Tail:Expression + ) + => concat( + appendValue + ( V + , HeadSize + , Head, Tail + , appendType(T) + ) + , appendValues(Evs, HeadSize, Head, Tail) + ) + + syntax AppendType ::= fixedSize(PathInExpression) + | variableSize(PathInExpression) + | "empty" + syntax AppendTypeOrError ::= AppendType | SemanticsError + syntax AppendTypeOrError ::= appendType(Type) [function, total] + + rule appendType(u8 ) => fixedSize(:: bytes_hooks :: append_u8) + rule appendType(u16 ) => fixedSize(:: bytes_hooks :: append_u16) + rule appendType(u32 ) => fixedSize(:: bytes_hooks :: append_u32) + rule appendType(u64 ) => fixedSize(:: bytes_hooks :: append_u64) + rule appendType(u128) => fixedSize(:: bytes_hooks :: append_u128) + rule appendType(u160) => fixedSize(:: bytes_hooks :: append_u160) + rule appendType(u256) => fixedSize(:: bytes_hooks :: append_u256) + + rule appendType(bool) => fixedSize(:: bytes_hooks :: append_bool) + rule appendType(()) => empty + rule appendType(str) => variableSize(:: bytes_hooks :: append_str) + rule appendType(T:Type) + => error("appendType: unrecognized type", ListItem(T)) + [owise] + + syntax NonEmptyStatementsOrError ::= appendValue + ( value: Expression + , headSize: Expression + , head: Identifier + , tail: Identifier + , appendFn: AppendTypeOrError + ) [function, total] + + rule appendValue + (... value: _Value:Expression + , headSize: _HeadSize:Expression + , head: _Head:Identifier + , tail: _Tail:Identifier + , appendFn: E:SemanticsError + ) + => E + rule appendValue + (... value: Value:Expression + , headSize: _HeadSize:Expression + , head: Head:Identifier + , tail: _Tail:Identifier + , appendFn: fixedSize(P:PathInExpression) + ) + => let Head = P ( Head , Value , .CallParamsList ); + .NonEmptyStatements + rule appendValue + (... value: Value:Expression + , headSize: HeadSize:Expression + , head: Head:Identifier + , tail: Tail:Identifier + , appendFn: variableSize(P:PathInExpression) + ) + => let Head = :: bytes_hooks :: append_u32 + ( Head + , HeadSize + (:: bytes_hooks :: length( Tail, .CallParamsList )) + , .CallParamsList + ); + let Tail = P ( Tail , Value , .CallParamsList ); + .NonEmptyStatements + rule appendValue + (... value: _Value:Expression + , headSize: _HeadSize:Expression + , head: _Head:Identifier + , tail: _Tail:Identifier + , appendFn: empty + ) + => .NonEmptyStatements + + // syntax ExpressionOrError ::= appendSingleValue + // ( bufferId: Identifier, value: Identifier, Type + // , headLength: ExpressionOrError, tailPrefixLength:Expression + // ) [function, total] + // syntax ExpressionOrError ::= appendSingleValue + // ( bufferId: Identifier, value: Identifier + // , headLength: Expression, tailPrefixLength:Expression + // , headFn: AppendOperationOrError + // , tailFn: AppendOperationOrError + // ) [function, total] + // rule appendSingleValue + // ( BufferId:Identifier, Value:Identifier, T:Type + // , HeadLength:Expression, TailPrefixLength:Expression + // ) + // => appendSingleValue(BufferId, Value, HeadLength, TailPrefixLength, headFunction(T), tailFunction(T)) + // rule appendSingleValue + // ( BufferId:Identifier, Value:Identifier, T:Type + // , HeadLength:Expression, TailPrefixLength:Expression + // ) + // => appendSingleValue(BufferId, Value, HeadLength, TailPrefixLength, headFunction(T), tailFunction(T)) + + // rule appendSingleValue + // ( BufferId:Identifier, Value:Identifier + // , HeadLength:Expression, TailPrefixLength:Expression + // , HeadFunction:AppendOperation, TailFunction:AppendOperation + // ) + // => v + // ( applyApend + // ( TailFunction + // , applyApend + // ( HeadFunction + // , BufferId + // , Value + // , HeadLength + TailPrefixLength + // ) + // , Value + // , ptrValue(null, tuple(.ValueList)) + // ) + // ) + // rule appendSingleValue + // ( _BufferId:Identifier, _Value:Identifier + // , _HeadLength:Expression, _TailPrefixLength:Expression + // , HeadFunction:SemanticsError, _TailFunction:AppendOperationOrError + // ) + // => e(HeadFunction) + // rule appendSingleValue + // ( _BufferId:Identifier, _Value:Identifier + // , _HeadLength:Expression, _TailPrefixLength:Expression + // , _HeadFunction:AppendOperation, TailFunction:SemanticsError + // ) + // => e(TailFunction) + + syntax AppendOperation ::= "id" + | "varHead" + | fixedHeadVarTail(PathInExpression) + syntax AppendOperationOrError ::= AppendOperation | SemanticsError + + syntax Expression ::= applyApend + ( AppendOperation + , buffer:Expression + , value: Expression + , length:Expression + ) [function, total] + rule applyApend(id:AppendOperation, E:Expression, _F:Expression, _G:Expression) + => E + rule applyApend(fixedHeadVarTail(P:PathInExpression), E:Expression, F:Expression, _G:Expression) + => P ( E , F , .CallParamsList ) + rule applyApend(varHead, E:Expression, _F:Expression, G:Expression) + => :: bytes_hooks :: append_u32 ( E , G , .CallParamsList ) + + syntax ExpressionOrError ::= headSize(Type) [function, total] + rule headSize(u8 ) => v(ptrValue(null, u32(32p32))) + rule headSize(u16 ) => v(ptrValue(null, u32(32p32))) + rule headSize(u32 ) => v(ptrValue(null, u32(32p32))) + rule headSize(u64 ) => v(ptrValue(null, u32(32p32))) + rule headSize(u128) => v(ptrValue(null, u32(32p32))) + rule headSize(u160) => v(ptrValue(null, u32(32p32))) + rule headSize(u256) => v(ptrValue(null, u32(32p32))) + + rule headSize(bool) => v(ptrValue(null, u32(32p32))) + rule headSize(()) => v(ptrValue(null, u32(0p32))) + rule headSize(str) => v(ptrValue(null, u32(32p32))) + rule headSize(T:Type) + => e(error("headSize: unrecognized type", ListItem(T:Type:KItem))) + [owise] + + syntax AppendOperationOrError ::= headFunction(Type) [function, total] + rule headFunction(u8 ) => fixedHeadVarTail(:: bytes_hooks :: append_u8) + rule headFunction(u16 ) => fixedHeadVarTail(:: bytes_hooks :: append_u16) + rule headFunction(u32 ) => fixedHeadVarTail(:: bytes_hooks :: append_u32) + rule headFunction(u64 ) => fixedHeadVarTail(:: bytes_hooks :: append_u64) + rule headFunction(u128) => fixedHeadVarTail(:: bytes_hooks :: append_u128) + rule headFunction(u160) => fixedHeadVarTail(:: bytes_hooks :: append_u160) + rule headFunction(u256) => fixedHeadVarTail(:: bytes_hooks :: append_u256) + + rule headFunction(bool) => fixedHeadVarTail(:: bytes_hooks :: append_bool) + rule headFunction(()) => id + rule headFunction(str) => varHead + rule headFunction(T:Type) + => error("headFunction: unrecognized type", ListItem(T)) + [owise] + + syntax AppendOperationOrError ::= tailFunction(Type) [function, total] + rule tailFunction(u8 ) => id + rule tailFunction(u16 ) => id + rule tailFunction(u32 ) => id + rule tailFunction(u64 ) => id + rule tailFunction(u128) => id + rule tailFunction(u160) => id + rule tailFunction(u256) => id + + rule tailFunction(bool) => id + rule tailFunction(()) => id + rule tailFunction(str) => fixedHeadVarTail(:: bytes_hooks :: append_str) + rule tailFunction(T:Type) + => error("tailFunction: unrecognized type", ListItem(T)) [owise] rule methodSignature(S:String, Ps:NormalizedFunctionParameterList) @@ -160,6 +408,14 @@ module ULM-CALLDATA-ENCODER rule signatureType(T) => error("Unknown type in signatureType:", ListItem(T)) [owise] + rule paramToEncodeValue(I:Identifier : T:Type) => I : T + rule paramToEncodeValue(I:SelfSort : T:Type) => I : T + + rule paramsToEncodeValues(.NormalizedFunctionParameterList) => .EncodeValues + rule paramsToEncodeValues(P:NormalizedFunctionParameter , Ps:NormalizedFunctionParameterList) + => paramToEncodeValue(P) , paramsToEncodeValues(Ps) + + endmodule ``` \ No newline at end of file diff --git a/ulm-semantics/main/encoding/syntax.md b/ulm-semantics/main/encoding/syntax.md index 9ec34ae4..ab2d07de 100644 --- a/ulm-semantics/main/encoding/syntax.md +++ b/ulm-semantics/main/encoding/syntax.md @@ -21,8 +21,14 @@ module ULM-ENCODING-SYNTAX syntax BytesOrError ::= methodSignature(String, NormalizedFunctionParameterList) [function, total] syntax ValueOrError ::= eventSignature(String, NormalizedFunctionParameterList) [function, total] - syntax ExpressionOrError ::= appendValue(bufferId: Identifier, value: Identifier, Type) [function, total] + syntax EncodeValue ::= Expression ":" Type + syntax EncodeValues ::= List{EncodeValue, ","} + // assumes that bufferId points to an empty buffer. + syntax NonEmptyStatementsOrError ::= encodeStatements(bufferId: Identifier, values: EncodeValues) [function, total] + + syntax EncodeValue ::= paramToEncodeValue(NormalizedFunctionParameter) [function, total] + syntax EncodeValues ::= paramsToEncodeValues(NormalizedFunctionParameterList) [function, total] endmodule module ULM-ENCODING-HELPER-SYNTAX diff --git a/ulm-semantics/main/hooks/bytes.md b/ulm-semantics/main/hooks/bytes.md index 32380b59..97f283a6 100644 --- a/ulm-semantics/main/hooks/bytes.md +++ b/ulm-semantics/main/hooks/bytes.md @@ -31,6 +31,7 @@ module ULM-SEMANTICS-HOOKS-BYTES | "length" [token] | "equals" [token] | "append_bool" [token] + | "append_bytes_raw" [token] | "append_u256" [token] | "append_u160" [token] | "append_u128" [token] @@ -144,6 +145,13 @@ module ULM-SEMANTICS-HOOKS-BYTES ) => ulmBytesAppendStr(BufferIdId, StrId) + rule + normalizedFunctionCall + ( :: bytes_hooks :: append_bytes_raw :: .PathExprSegments + , BufferIdId:Ptr, ToAppendId:Ptr, .PtrList + ) + => ulmBytesAppendBytesRaw(BufferIdId, ToAppendId) + rule normalizedFunctionCall ( :: bytes_hooks :: decode_u256 :: .PathExprSegments @@ -232,6 +240,8 @@ module ULM-SEMANTICS-HOOKS-BYTES | ulmBytesAppendInt(Expression, Expression) [seqstrict] | ulmBytesAppendInt(UlmExpression, Int) [strict(1)] | ulmBytesAppendBool(Expression, Expression) [seqstrict] + | ulmBytesAppendBytesRaw(Expression, Expression) [seqstrict] + | ulmBytesAppendBytesRaw(UlmExpression, UlmExpression) [seqstrict] | ulmBytesAppendStr(Expression, Expression) [seqstrict] | ulmBytesAppendBytes(UlmExpression, Bytes) [strict(1)] | ulmBytesAppendLenAndBytes(UlmExpression, Bytes) [strict(1)] @@ -297,6 +307,11 @@ module ULM-SEMANTICS-HOOKS-BYTES rule ulmBytesAppendStr(ptrValue(_, u64(BytesId)), ptrValue(_, Value:String)) => ulmBytesAppendLenAndBytes(ulmBytesId(BytesId), String2Bytes(Value)) + rule ulmBytesAppendBytesRaw(ptrValue(_, u64(BytesId)), ptrValue(_, u64(ToAppendId))) + => ulmBytesAppendBytesRaw(ulmBytesId(BytesId), ulmBytesId(ToAppendId)) + rule ulmBytesAppendBytesRaw(ulmBytesValue(B:Bytes), ulmBytesValue(ToAppend)) + => ulmBytesNew(B +Bytes ToAppend) + rule ulmBytesAppendBytes(ulmBytesValue(B:Bytes), Value:Bytes) => ulmBytesNew(B +Bytes Value) diff --git a/ulm-semantics/main/preprocessing/endpoints.md b/ulm-semantics/main/preprocessing/endpoints.md index ee261139..26eff0a7 100644 --- a/ulm-semantics/main/preprocessing/endpoints.md +++ b/ulm-semantics/main/preprocessing/endpoints.md @@ -48,7 +48,7 @@ module ULM-PREPROCESSING-ENDPOINTS (... wrapperMethod: WrapperMethod , params: Params , method: ImplementationMethod - , appendReturn: appendValue(buffer_id, return_value, ReturnType) + , appendReturn: encodeStatements(buffer_id, (return_value : ReturnType , .EncodeValues)) , decodeStatements: decodeParams(0, Params) ) @@ -58,7 +58,7 @@ module ULM-PREPROCESSING-ENDPOINTS (... wrapperMethod: WrapperMethod:PathInExpression , params: Params:NormalizedFunctionParameterList , method: ImplementationMethod:Identifier - , appendReturn: v(Append:Expression) + , appendReturn: Append:NonEmptyStatements , decodeStatements: Decode:NonEmptyStatements ) => .K ... @@ -77,11 +77,14 @@ module ULM-PREPROCESSING-ENDPOINTS :: state_hooks :: setGasLeft(gas , .CallParamsList); concatNonEmptyStatements ( Decode - , let return_value = callMethod(ImplementationMethod, Params); - let buffer_id = :: bytes_hooks :: empty(.CallParamsList); - let buffer_id = Append; - :: state_hooks :: setOutput(buffer_id , .CallParamsList); - :: state_hooks :: setStatus(:: ulm :: EVMC_SUCCESS , .CallParamsList); + , concatNonEmptyStatements + ( let return_value = callMethod(ImplementationMethod, Params); + let buffer_id = :: bytes_hooks :: empty(.CallParamsList); + Append + , :: state_hooks :: setOutput(buffer_id , .CallParamsList); + :: state_hooks :: setStatus(:: ulm :: EVMC_SUCCESS , .CallParamsList); + .NonEmptyStatements + ) ) }) @@ -164,6 +167,7 @@ module ULM-PREPROCESSING-ENDPOINTS | "append_u160" [token] | "append_u256" [token] | "append_bool" [token] + | "append_str" [token] | "decode_u8" [token] | "decode_u16" [token] | "decode_u32" [token] @@ -175,6 +179,7 @@ module ULM-PREPROCESSING-ENDPOINTS | "decode_signature" [token] | "empty" [token] | "equals" [token] + | "head_length" [token] | "ulm" [token] | "ulmWrap##init" [token] | "CallData" [token] @@ -246,15 +251,15 @@ module ULM-PREPROCESSING-ENDPOINTS rule decodeForType(u256) => v(:: bytes_hooks :: decode_u256 ( buffer_id , .CallParamsList )) syntax Expression ::= callMethod(Identifier, NormalizedFunctionParameterList) [function, total] - syntax Expression ::= callMethod(Identifier, CallParamsList) [function, total] + syntax Expression ::= #callMethod(Identifier, CallParamsList) [function, total] syntax CallParamsList ::= buildArgs(Int, NormalizedFunctionParameterList) [function, total] rule callMethod(Method:Identifier, Ps:NormalizedFunctionParameterList) - => callMethod(Method, buildArgs(0, Ps)) + => #callMethod(Method, buildArgs(0, Ps)) - rule callMethod(Method:Identifier, .CallParamsList) + rule #callMethod(Method:Identifier, .CallParamsList) => self . Method ( ) - rule callMethod(Method:Identifier, (_ , _:CallParamsList) #as Ps:CallParamsList) + rule #callMethod(Method:Identifier, (_ , _:CallParamsList) #as Ps:CallParamsList) => self . Method ( Ps ) rule buildArgs(_:Int, .NormalizedFunctionParameterList) => .CallParamsList diff --git a/ulm-semantics/main/preprocessing/events.md b/ulm-semantics/main/preprocessing/events.md index d0c4288d..d6e28088 100644 --- a/ulm-semantics/main/preprocessing/events.md +++ b/ulm-semantics/main/preprocessing/events.md @@ -19,7 +19,7 @@ module ULM-PREPROCESSING-EVENTS syntax UkmInstruction ::= #ulmPreprocessEvent ( method: PathInExpression - , appendLastParam: ExpressionOrError + , appendLastParam: NonEmptyStatementsOrError , logIdentifier: IdentifierOrError , eventSignature: ValueOrError ) @@ -34,7 +34,13 @@ module ULM-PREPROCESSING-EVENTS // but the last one are indexed. We should handle generic events. => #ulmPreprocessEvent ( Method - , appendParamToBytes(data, last(Param, Params)) + , encodeStatements + ( data + , paramsToEncodeValues + ( last(Param, Params) + , .NormalizedFunctionParameterList + ) + ) , findLogIdentifier(1 +Int length(Params)) , eventSignature(EventName, (Param , Params)) ) @@ -49,7 +55,7 @@ module ULM-PREPROCESSING-EVENTS #ulmPreprocessEvent (... method: Method:PathInExpression - , appendLastParam: v(AppendLast:Expression) + , appendLastParam: AppendLast:NonEmptyStatements , logIdentifier: LogIdentifier:Identifier , eventSignature: EventSignature:Value ) @@ -61,29 +67,22 @@ module ULM-PREPROCESSING-EVENTS empty => block({ .InnerAttributes - let data = :: bytes_hooks :: empty ( .CallParamsList ); - let data = AppendLast; - :: ulm :: LogIdentifier - ( ptrValue(null, EventSignature) - , concatCallParamsList - ( paramsToArgs(allButLast(Param, Params)) - , (data , .CallParamsList) - ) - ); - .NonEmptyStatements + concatNonEmptyStatements + ( let data = :: bytes_hooks :: empty ( .CallParamsList ); + AppendLast + , :: ulm :: LogIdentifier + ( ptrValue(null, EventSignature) + , concatCallParamsList + ( paramsToArgs(allButLast(Param, Params)) + , (data , .CallParamsList) + ) + ); + .NonEmptyStatements + ) }) () - syntax ExpressionOrError ::= appendParamToBytes - ( bufferId: Identifier - , NormalizedFunctionParameter - ) [function, total] - rule appendParamToBytes(B:Identifier, (I:Identifier : T:Type)) => appendValue(B, I, T) - rule appendParamToBytes(B, P) - => e(error("appendParamToBytes: unrecognized param", ListItem(B) ListItem(P))) - [owise] - syntax IdentifierOrError ::= findLogIdentifier(Int) [function, total] rule findLogIdentifier(1) => Log1 rule findLogIdentifier(2) => Log2 diff --git a/ulm-semantics/main/preprocessing/syntax.md b/ulm-semantics/main/preprocessing/syntax.md index 0a34d8a9..5e80e05e 100644 --- a/ulm-semantics/main/preprocessing/syntax.md +++ b/ulm-semantics/main/preprocessing/syntax.md @@ -32,7 +32,7 @@ module ULM-PREPROCESSING-SYNTAX-PRIVATE ( wrapperMethod: PathInExpression , params: NormalizedFunctionParameterList , method: Identifier - , appendReturn: ExpressionOrError + , appendReturn: NonEmptyStatementsOrError , decodeStatements: NonEmptyStatementsOrError ) | ulmAddEndpointSignature(signature: BytesOrError, method: Identifier) From bd3767d0bf59967a582d09bdaac0b5da5b093de7 Mon Sep 17 00:00:00 2001 From: Virgil Date: Sat, 9 Nov 2024 00:54:45 +0200 Subject: [PATCH 02/10] cleanup --- ulm-semantics/main/encoding/encoder.md | 118 ------------------------- 1 file changed, 118 deletions(-) diff --git a/ulm-semantics/main/encoding/encoder.md b/ulm-semantics/main/encoding/encoder.md index 7c075c52..a32a6ab8 100644 --- a/ulm-semantics/main/encoding/encoder.md +++ b/ulm-semantics/main/encoding/encoder.md @@ -109,27 +109,6 @@ module ULM-CALLDATA-ENCODER rule encodeFunctionParams(.List, .List, B:Bytes) => B - // rule appendValue(BufferId:Identifier, Value:Identifier, u8) - // => v(:: bytes_hooks :: append_u8 ( BufferId , Value , .CallParamsList )) - // rule appendValue(BufferId:Identifier, Value:Identifier, u16) - // => v(:: bytes_hooks :: append_u16 ( BufferId , Value , .CallParamsList )) - // rule appendValue(BufferId:Identifier, Value:Identifier, u32) - // => v(:: bytes_hooks :: append_u32 ( BufferId , Value , .CallParamsList )) - // rule appendValue(BufferId:Identifier, Value:Identifier, u64) - // => v(:: bytes_hooks :: append_u64 ( BufferId , Value , .CallParamsList )) - // rule appendValue(BufferId:Identifier, Value:Identifier, u128) - // => v(:: bytes_hooks :: append_u128 ( BufferId , Value , .CallParamsList )) - // rule appendValue(BufferId:Identifier, Value:Identifier, u160) - // => v(:: bytes_hooks :: append_u160 ( BufferId , Value , .CallParamsList )) - // rule appendValue(BufferId:Identifier, Value:Identifier, u256) - // => v(:: bytes_hooks :: append_u256 ( BufferId , Value , .CallParamsList )) - // rule appendValue(BufferId:Identifier, Value:Identifier, bool) - // => v(:: bytes_hooks :: append_bool ( BufferId , Value , .CallParamsList )) - // rule appendValue(BufferId:Identifier, _Value:Identifier, ()) => v(BufferId) - // rule appendValue(BufferId:Identifier, Value:Identifier, T:Type) - // => e(error("appendValue: unrecognized type", ListItem(BufferId) ListItem(Value) ListItem(T))) - // [owise] - syntax Identifier ::= "ulm#head_size" [token] | "ulm#head" [token] | "ulm#tail" [token] @@ -256,76 +235,11 @@ module ULM-CALLDATA-ENCODER ) => .NonEmptyStatements - // syntax ExpressionOrError ::= appendSingleValue - // ( bufferId: Identifier, value: Identifier, Type - // , headLength: ExpressionOrError, tailPrefixLength:Expression - // ) [function, total] - // syntax ExpressionOrError ::= appendSingleValue - // ( bufferId: Identifier, value: Identifier - // , headLength: Expression, tailPrefixLength:Expression - // , headFn: AppendOperationOrError - // , tailFn: AppendOperationOrError - // ) [function, total] - // rule appendSingleValue - // ( BufferId:Identifier, Value:Identifier, T:Type - // , HeadLength:Expression, TailPrefixLength:Expression - // ) - // => appendSingleValue(BufferId, Value, HeadLength, TailPrefixLength, headFunction(T), tailFunction(T)) - // rule appendSingleValue - // ( BufferId:Identifier, Value:Identifier, T:Type - // , HeadLength:Expression, TailPrefixLength:Expression - // ) - // => appendSingleValue(BufferId, Value, HeadLength, TailPrefixLength, headFunction(T), tailFunction(T)) - - // rule appendSingleValue - // ( BufferId:Identifier, Value:Identifier - // , HeadLength:Expression, TailPrefixLength:Expression - // , HeadFunction:AppendOperation, TailFunction:AppendOperation - // ) - // => v - // ( applyApend - // ( TailFunction - // , applyApend - // ( HeadFunction - // , BufferId - // , Value - // , HeadLength + TailPrefixLength - // ) - // , Value - // , ptrValue(null, tuple(.ValueList)) - // ) - // ) - // rule appendSingleValue - // ( _BufferId:Identifier, _Value:Identifier - // , _HeadLength:Expression, _TailPrefixLength:Expression - // , HeadFunction:SemanticsError, _TailFunction:AppendOperationOrError - // ) - // => e(HeadFunction) - // rule appendSingleValue - // ( _BufferId:Identifier, _Value:Identifier - // , _HeadLength:Expression, _TailPrefixLength:Expression - // , _HeadFunction:AppendOperation, TailFunction:SemanticsError - // ) - // => e(TailFunction) - syntax AppendOperation ::= "id" | "varHead" | fixedHeadVarTail(PathInExpression) syntax AppendOperationOrError ::= AppendOperation | SemanticsError - syntax Expression ::= applyApend - ( AppendOperation - , buffer:Expression - , value: Expression - , length:Expression - ) [function, total] - rule applyApend(id:AppendOperation, E:Expression, _F:Expression, _G:Expression) - => E - rule applyApend(fixedHeadVarTail(P:PathInExpression), E:Expression, F:Expression, _G:Expression) - => P ( E , F , .CallParamsList ) - rule applyApend(varHead, E:Expression, _F:Expression, G:Expression) - => :: bytes_hooks :: append_u32 ( E , G , .CallParamsList ) - syntax ExpressionOrError ::= headSize(Type) [function, total] rule headSize(u8 ) => v(ptrValue(null, u32(32p32))) rule headSize(u16 ) => v(ptrValue(null, u32(32p32))) @@ -342,38 +256,6 @@ module ULM-CALLDATA-ENCODER => e(error("headSize: unrecognized type", ListItem(T:Type:KItem))) [owise] - syntax AppendOperationOrError ::= headFunction(Type) [function, total] - rule headFunction(u8 ) => fixedHeadVarTail(:: bytes_hooks :: append_u8) - rule headFunction(u16 ) => fixedHeadVarTail(:: bytes_hooks :: append_u16) - rule headFunction(u32 ) => fixedHeadVarTail(:: bytes_hooks :: append_u32) - rule headFunction(u64 ) => fixedHeadVarTail(:: bytes_hooks :: append_u64) - rule headFunction(u128) => fixedHeadVarTail(:: bytes_hooks :: append_u128) - rule headFunction(u160) => fixedHeadVarTail(:: bytes_hooks :: append_u160) - rule headFunction(u256) => fixedHeadVarTail(:: bytes_hooks :: append_u256) - - rule headFunction(bool) => fixedHeadVarTail(:: bytes_hooks :: append_bool) - rule headFunction(()) => id - rule headFunction(str) => varHead - rule headFunction(T:Type) - => error("headFunction: unrecognized type", ListItem(T)) - [owise] - - syntax AppendOperationOrError ::= tailFunction(Type) [function, total] - rule tailFunction(u8 ) => id - rule tailFunction(u16 ) => id - rule tailFunction(u32 ) => id - rule tailFunction(u64 ) => id - rule tailFunction(u128) => id - rule tailFunction(u160) => id - rule tailFunction(u256) => id - - rule tailFunction(bool) => id - rule tailFunction(()) => id - rule tailFunction(str) => fixedHeadVarTail(:: bytes_hooks :: append_str) - rule tailFunction(T:Type) - => error("tailFunction: unrecognized type", ListItem(T)) - [owise] - rule methodSignature(S:String, Ps:NormalizedFunctionParameterList) => encodeFunctionSignatureAsBytes(concat(concat(S +String "(", signatureTypes(Ps)), ")")) From 28bf9501aa5b7e4c0928d9b8d2e273b390ed2c3d Mon Sep 17 00:00:00 2001 From: Virgil Date: Sat, 9 Nov 2024 00:58:41 +0200 Subject: [PATCH 03/10] cleanup --- ulm-semantics/main/encoding/encoder.md | 5 ----- 1 file changed, 5 deletions(-) diff --git a/ulm-semantics/main/encoding/encoder.md b/ulm-semantics/main/encoding/encoder.md index a32a6ab8..8b5dbb2b 100644 --- a/ulm-semantics/main/encoding/encoder.md +++ b/ulm-semantics/main/encoding/encoder.md @@ -235,11 +235,6 @@ module ULM-CALLDATA-ENCODER ) => .NonEmptyStatements - syntax AppendOperation ::= "id" - | "varHead" - | fixedHeadVarTail(PathInExpression) - syntax AppendOperationOrError ::= AppendOperation | SemanticsError - syntax ExpressionOrError ::= headSize(Type) [function, total] rule headSize(u8 ) => v(ptrValue(null, u32(32p32))) rule headSize(u16 ) => v(ptrValue(null, u32(32p32))) From 72dc6b695e2bb195e0645114ab6139dcc776e292 Mon Sep 17 00:00:00 2001 From: Virgil Date: Mon, 11 Nov 2024 19:30:42 +0200 Subject: [PATCH 04/10] tmp --- tests/ulm-with-contract/types.str-raw.run | 21 +++++++++++++++++++++ tests/ulm-with-contract/types.str.run | 4 +++- ulm-semantics/main/hooks/bytes.md | 10 +++++++++- ulm-semantics/test/execution.md | 22 ++++++++++++++++++++-- 4 files changed, 53 insertions(+), 4 deletions(-) create mode 100644 tests/ulm-with-contract/types.str-raw.run diff --git a/tests/ulm-with-contract/types.str-raw.run b/tests/ulm-with-contract/types.str-raw.run new file mode 100644 index 00000000..4e875994 --- /dev/null +++ b/tests/ulm-with-contract/types.str-raw.run @@ -0,0 +1,21 @@ +push "strEndpoint"; +hold_string_from_test_stack; +hold_list_values_from_test_stack; +hold_list_values_from_test_stack; +encode_call_data; + +return_value; +mock CallData; + +call_contract 12345; +return_value; +check_eq (); + +push_status; +check_eq 2; + +check_raw_output + b"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x20" + + b"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x05" + + b"Hello\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + diff --git a/tests/ulm-with-contract/types.str.run b/tests/ulm-with-contract/types.str.run index efc2c17d..b21c2243 100644 --- a/tests/ulm-with-contract/types.str.run +++ b/tests/ulm-with-contract/types.str.run @@ -13,5 +13,7 @@ check_eq (); push_status; check_eq 2; -output_to_arg; call :: test_helpers :: decode_single_str; return_value; +output_to_arg; +call :: test_helpers :: decode_single_str; +return_value; check_eq "Hello" diff --git a/ulm-semantics/main/hooks/bytes.md b/ulm-semantics/main/hooks/bytes.md index 97f283a6..2fe8eef7 100644 --- a/ulm-semantics/main/hooks/bytes.md +++ b/ulm-semantics/main/hooks/bytes.md @@ -316,7 +316,15 @@ module ULM-SEMANTICS-HOOKS-BYTES => ulmBytesNew(B +Bytes Value) rule ulmBytesAppendLenAndBytes(ulmBytesValue(First:Bytes), Second:Bytes) - => ulmBytesNew(First +Bytes Int2Bytes(2, lengthBytes(Second), BE) +Bytes Second) + => ulmBytesNew + ( First + +Bytes Int2Bytes(32, lengthBytes(Second), BE) + +Bytes padRightBytes + ( Second + , ((lengthBytes(Second) +Int 31) /Int 32) *Int 32 + , 0 + ) + ) requires lengthBytes(Second) expect_cancel) => .K + syntax Bytes ::= concat(BytesList) [function, total] + rule concat(.BytesList) => b"" + rule concat(B:Bytes + Bs:BytesList) => B +Bytes concat(Bs) + + syntax Int ::= size(BytesList) [function, total] + rule size(.BytesList) => 0 + rule size(_:Bytes + Bs:BytesList) => 1 +Int size(Bs) + + rule check_raw_output (L:BytesList => concat(L) + .BytesList) + requires size(L) >Int 1 + rule + + check_raw_output B:Bytes + .BytesList => .K + ... + + B:Bytes + endmodule ``` From f14a42c518abd9e1b5b7321eedcf302118e07e2d Mon Sep 17 00:00:00 2001 From: Virgil Date: Mon, 11 Nov 2024 21:12:24 +0200 Subject: [PATCH 05/10] Fix tests --- .../test_bytes_hooks.appendstr.run | 6 +-- tests/ulm-with-contract/erc_20_token.1.run | 44 +++++++++---------- tests/ulm-with-contract/storage.256.run | 4 +- tests/ulm-with-contract/storage.key.run | 4 +- tests/ulm-with-contract/storage.simple.run | 4 +- ulm-semantics/main/hooks/bytes.md | 9 ++-- 6 files changed, 37 insertions(+), 34 deletions(-) diff --git a/tests/ulm-no-contract/test_bytes_hooks.appendstr.run b/tests/ulm-no-contract/test_bytes_hooks.appendstr.run index 400b52c2..f49ebb8b 100644 --- a/tests/ulm-no-contract/test_bytes_hooks.appendstr.run +++ b/tests/ulm-no-contract/test_bytes_hooks.appendstr.run @@ -3,11 +3,11 @@ call :: test_bytes_hooks :: append_str; return_value_to_arg; call :: bytes_hooks :: length; return_value; -check_eq 7_u32; +check_eq 64_u32; -push "Everyone"; +push "Everyone12345678901234567890123456789012"; call :: test_bytes_hooks :: append_str; return_value_to_arg; call :: bytes_hooks :: length; return_value; -check_eq 10_u32 +check_eq 96_u32 diff --git a/tests/ulm-with-contract/erc_20_token.1.run b/tests/ulm-with-contract/erc_20_token.1.run index f5c63e56..72953e0e 100644 --- a/tests/ulm-with-contract/erc_20_token.1.run +++ b/tests/ulm-with-contract/erc_20_token.1.run @@ -1,28 +1,28 @@ -list_mock GetAccountStorageHook ( 11059124170230400219182520145867018696635045254189466511817698468614930762963 ) ulmIntResult(0, u256); -list_mock SetAccountStorageHook ( 11059124170230400219182520145867018696635045254189466511817698468614930762963 , 10000 ) ulmNoResult(); -list_mock GetAccountStorageHook ( 115494845046723600673943990597816811669707739681772931244236289759170204726560 ) ulmIntResult(0, u256); -list_mock SetAccountStorageHook ( 115494845046723600673943990597816811669707739681772931244236289759170204726560 , 10000 ) ulmNoResult(); -list_mock GetAccountStorageHook ( 115494845046723600673943990597816811669707739681772931244236289759170204726560 ) ulmIntResult(10000, u256); -list_mock GetAccountStorageHook ( 115494845046723600673943990597816811669707739681772931244236289759170204726560 ) ulmIntResult(10000, u256); -list_mock GetAccountStorageHook ( 115494845046723600673943990597816811669707739681772931244236289759170204726560 ) ulmIntResult(10000, u256); -list_mock SetAccountStorageHook ( 115494845046723600673943990597816811669707739681772931244236289759170204726560 , 9900 ) ulmNoResult(); -list_mock GetAccountStorageHook ( 17171626450567201640701347902808840427582371480602455275836469707331258301780 ) ulmIntResult(0, u256); -list_mock SetAccountStorageHook ( 17171626450567201640701347902808840427582371480602455275836469707331258301780 , 100 ) ulmNoResult(); +list_mock GetAccountStorageHook ( 13032332009337290780939164280742955473285243463246449969298152790977293574652 ) ulmIntResult(0, u256); +list_mock SetAccountStorageHook ( 13032332009337290780939164280742955473285243463246449969298152790977293574652 , 10000 ) ulmNoResult(); +list_mock GetAccountStorageHook ( 61159765391625381932700807532824927387505868579121206115135228514320059425645 ) ulmIntResult(0, u256); +list_mock SetAccountStorageHook ( 61159765391625381932700807532824927387505868579121206115135228514320059425645 , 10000 ) ulmNoResult(); +list_mock GetAccountStorageHook ( 61159765391625381932700807532824927387505868579121206115135228514320059425645 ) ulmIntResult(10000, u256); +list_mock GetAccountStorageHook ( 61159765391625381932700807532824927387505868579121206115135228514320059425645 ) ulmIntResult(10000, u256); +list_mock GetAccountStorageHook ( 61159765391625381932700807532824927387505868579121206115135228514320059425645 ) ulmIntResult(10000, u256); +list_mock SetAccountStorageHook ( 61159765391625381932700807532824927387505868579121206115135228514320059425645 , 9900 ) ulmNoResult(); +list_mock GetAccountStorageHook ( 107935355587284645605585039702009686485686559005730386557515578263121021727641 ) ulmIntResult(0, u256); +list_mock SetAccountStorageHook ( 107935355587284645605585039702009686485686559005730386557515578263121021727641 , 100 ) ulmNoResult(); list_mock Log3Hook ( 100389287136786176327247604509743168900146139575972864366142685224231313322991 , 1010101 , 2020202 , b"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00d" ) ulmNoResult(); -list_mock GetAccountStorageHook ( 115494845046723600673943990597816811669707739681772931244236289759170204726560 ) ulmIntResult(9900, u256); -list_mock GetAccountStorageHook ( 17171626450567201640701347902808840427582371480602455275836469707331258301780 ) ulmIntResult(100, u256); -list_mock SetAccountStorageHook ( 97321503972240892886219376522881926110074550168465622121824657360422868161783 , 200 ) ulmNoResult(); +list_mock GetAccountStorageHook ( 61159765391625381932700807532824927387505868579121206115135228514320059425645 ) ulmIntResult(9900, u256); +list_mock GetAccountStorageHook ( 107935355587284645605585039702009686485686559005730386557515578263121021727641 ) ulmIntResult(100, u256); +list_mock SetAccountStorageHook ( 6299478510657022222390882510197411465571447485061513230872540120223652878023 , 200 ) ulmNoResult(); list_mock Log3Hook ( 63486140976153616755203102783360879283472101686154884697241723088393386309925 , 1010101 , 3030303 , b"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xc8" ) ulmNoResult(); -list_mock GetAccountStorageHook ( 97321503972240892886219376522881926110074550168465622121824657360422868161783 ) ulmIntResult(200, u256); -list_mock SetAccountStorageHook ( 97321503972240892886219376522881926110074550168465622121824657360422868161783 , 0 ) ulmNoResult(); -list_mock GetAccountStorageHook ( 115494845046723600673943990597816811669707739681772931244236289759170204726560 ) ulmIntResult(9900, u256); -list_mock GetAccountStorageHook ( 115494845046723600673943990597816811669707739681772931244236289759170204726560 ) ulmIntResult(9900, u256); -list_mock SetAccountStorageHook ( 115494845046723600673943990597816811669707739681772931244236289759170204726560 , 9700 ) ulmNoResult(); -list_mock GetAccountStorageHook ( 17171626450567201640701347902808840427582371480602455275836469707331258301780 ) ulmIntResult(100, u256); -list_mock SetAccountStorageHook ( 17171626450567201640701347902808840427582371480602455275836469707331258301780 , 300 ) ulmNoResult(); +list_mock GetAccountStorageHook ( 6299478510657022222390882510197411465571447485061513230872540120223652878023 ) ulmIntResult(200, u256); +list_mock SetAccountStorageHook ( 6299478510657022222390882510197411465571447485061513230872540120223652878023 , 0 ) ulmNoResult(); +list_mock GetAccountStorageHook ( 61159765391625381932700807532824927387505868579121206115135228514320059425645 ) ulmIntResult(9900, u256); +list_mock GetAccountStorageHook ( 61159765391625381932700807532824927387505868579121206115135228514320059425645 ) ulmIntResult(9900, u256); +list_mock SetAccountStorageHook ( 61159765391625381932700807532824927387505868579121206115135228514320059425645 , 9700 ) ulmNoResult(); +list_mock GetAccountStorageHook ( 107935355587284645605585039702009686485686559005730386557515578263121021727641 ) ulmIntResult(100, u256); +list_mock SetAccountStorageHook ( 107935355587284645605585039702009686485686559005730386557515578263121021727641 , 300 ) ulmNoResult(); list_mock Log3Hook ( 100389287136786176327247604509743168900146139575972864366142685224231313322991 , 1010101 , 2020202 , b"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xc8" ) ulmNoResult(); -list_mock GetAccountStorageHook ( 115494845046723600673943990597816811669707739681772931244236289759170204726560 ) ulmIntResult(9700, u256); -list_mock GetAccountStorageHook ( 17171626450567201640701347902808840427582371480602455275836469707331258301780 ) ulmIntResult(300, u256); +list_mock GetAccountStorageHook ( 61159765391625381932700807532824927387505868579121206115135228514320059425645 ) ulmIntResult(9700, u256); +list_mock GetAccountStorageHook ( 107935355587284645605585039702009686485686559005730386557515578263121021727641 ) ulmIntResult(300, u256); push "uint256"; hold_list_values_from_test_stack; diff --git a/tests/ulm-with-contract/storage.256.run b/tests/ulm-with-contract/storage.256.run index b5b52615..f20b63a9 100644 --- a/tests/ulm-with-contract/storage.256.run +++ b/tests/ulm-with-contract/storage.256.run @@ -1,5 +1,5 @@ -mock SetAccountStorageHook ( 47586510880955265726688953653028435069486243252926274554489699639913455891751 , 1000000000000000000000000000000000000000000000000000000000000 ) ulmNoResult(); -mock GetAccountStorageHook ( 47586510880955265726688953653028435069486243252926274554489699639913455891751 ) ulmIntResult(1000000000000000000000000000000000000000000000000000000000000, u256); +mock SetAccountStorageHook ( 81899343944223093934060911023235694134954301913235101281428181165721203435003 , 1000000000000000000000000000000000000000000000000000000000000 ) ulmNoResult(); +mock GetAccountStorageHook ( 81899343944223093934060911023235694134954301913235101281428181165721203435003 ) ulmIntResult(1000000000000000000000000000000000000000000000000000000000000, u256); push "setMyData256"; hold_string_from_test_stack; diff --git a/tests/ulm-with-contract/storage.key.run b/tests/ulm-with-contract/storage.key.run index e89191c8..2f9d282f 100644 --- a/tests/ulm-with-contract/storage.key.run +++ b/tests/ulm-with-contract/storage.key.run @@ -1,5 +1,5 @@ -mock SetAccountStorageHook ( 10244917065751466042072482011607924022453580028001931068470547844249081769915 , 123 ) ulmNoResult(); -mock GetAccountStorageHook ( 10244917065751466042072482011607924022453580028001931068470547844249081769915 ) ulmIntResult(123, u256); +mock SetAccountStorageHook ( 89307555350153532481150451243271458944170707741354029868021544305102042370102 , 123 ) ulmNoResult(); +mock GetAccountStorageHook ( 89307555350153532481150451243271458944170707741354029868021544305102042370102 ) ulmIntResult(123, u256); push "setMyDataKey"; hold_string_from_test_stack; diff --git a/tests/ulm-with-contract/storage.simple.run b/tests/ulm-with-contract/storage.simple.run index 6ad0b98e..67d06534 100644 --- a/tests/ulm-with-contract/storage.simple.run +++ b/tests/ulm-with-contract/storage.simple.run @@ -1,5 +1,5 @@ -mock SetAccountStorageHook ( 73866358942311723187445361469509963283744060252826659833950887638461707973283 , 123 ) ulmNoResult(); -mock GetAccountStorageHook ( 73866358942311723187445361469509963283744060252826659833950887638461707973283 ) ulmIntResult(123, u256); +mock SetAccountStorageHook ( 2566766180763832229052383091904627608042490431692515280991237530682175269032 , 123 ) ulmNoResult(); +mock GetAccountStorageHook ( 2566766180763832229052383091904627608042490431692515280991237530682175269032 ) ulmIntResult(123, u256); push "setMyData"; hold_string_from_test_stack; diff --git a/ulm-semantics/main/hooks/bytes.md b/ulm-semantics/main/hooks/bytes.md index 2fe8eef7..5111ea00 100644 --- a/ulm-semantics/main/hooks/bytes.md +++ b/ulm-semantics/main/hooks/bytes.md @@ -353,15 +353,18 @@ module ULM-SEMANTICS-HOOKS-BYTES requires isSignedInt(T) andBool 32 <=Int lengthBytes(B) rule ulmBytesDecode(ulmBytesValue(B:Bytes), str) => ulmBytesDecodeStr - ( Bytes2Int(substrBytes(B, 0, 2), BE, Signed) - , substrBytes(B, 2, lengthBytes(B)) + ( Bytes2Int(substrBytes(B, 0, 32), BE, Signed) + , substrBytes(B, 32, lengthBytes(B)) ) requires 2 <=Int lengthBytes(B) rule ulmBytesDecodeInt(Value:Int, B:Bytes, T:Type) => ulmBytesDecode(integerToValue(Value, T), B) rule ulmBytesDecodeStr(Len:Int, B:Bytes) - => ulmBytesDecode(Bytes2String(substrBytes(B, 0, Len)), substrBytes(B, Len, lengthBytes(B))) + => ulmBytesDecode + ( Bytes2String(substrBytes(B, 0, Len)) + , substrBytes(B, ((Len +Int 31) /Int 32) *Int 32, lengthBytes(B)) + ) requires 0 <=Int Len andBool Len <=Int lengthBytes(B) rule ulmBytesDecode(Value:Value, B:Bytes) From 384aef2629e3aff1067a7ad28b08db03766ea7dd Mon Sep 17 00:00:00 2001 From: Virgil Date: Tue, 12 Nov 2024 18:45:08 +0200 Subject: [PATCH 06/10] Remove unneeded identifier --- ulm-semantics/main/preprocessing/endpoints.md | 1 - 1 file changed, 1 deletion(-) diff --git a/ulm-semantics/main/preprocessing/endpoints.md b/ulm-semantics/main/preprocessing/endpoints.md index 26eff0a7..e4326892 100644 --- a/ulm-semantics/main/preprocessing/endpoints.md +++ b/ulm-semantics/main/preprocessing/endpoints.md @@ -179,7 +179,6 @@ module ULM-PREPROCESSING-ENDPOINTS | "decode_signature" [token] | "empty" [token] | "equals" [token] - | "head_length" [token] | "ulm" [token] | "ulmWrap##init" [token] | "CallData" [token] From 8254fa2076edaccba59d17c729c06c41cb2e8d9d Mon Sep 17 00:00:00 2001 From: Virgil Date: Wed, 20 Nov 2024 14:32:37 +0200 Subject: [PATCH 07/10] Renamee encodeStatements to codegenValuesEncoder --- ulm-semantics/main/encoding/encoder.md | 12 ++++++------ ulm-semantics/main/encoding/syntax.md | 2 +- ulm-semantics/main/preprocessing/endpoints.md | 2 +- ulm-semantics/main/preprocessing/events.md | 2 +- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/ulm-semantics/main/encoding/encoder.md b/ulm-semantics/main/encoding/encoder.md index 8b5dbb2b..fc37d305 100644 --- a/ulm-semantics/main/encoding/encoder.md +++ b/ulm-semantics/main/encoding/encoder.md @@ -113,20 +113,20 @@ module ULM-CALLDATA-ENCODER | "ulm#head" [token] | "ulm#tail" [token] - syntax NonEmptyStatementsOrError ::= #encodeStatements + syntax NonEmptyStatementsOrError ::= #codegenValuesEncoder ( bufferId: Identifier , headSize: ExpressionOrError , append: NonEmptyStatementsOrError ) [function, total] - rule encodeStatements(... bufferId: BufferId:Identifier, values: Values:EncodeValues) - => #encodeStatements(BufferId, totalHeadSize(Values), appendValues(Values, ulm#head_size, ulm#head, ulm#tail)) + rule codegenValuesEncoder(... bufferId: BufferId:Identifier, values: Values:EncodeValues) + => #codegenValuesEncoder(BufferId, totalHeadSize(Values), appendValues(Values, ulm#head_size, ulm#head, ulm#tail)) - rule #encodeStatements(_BufferId:Identifier, e(HeadSize:SemanticsError), _AppendValues:NonEmptyStatementsOrError) + rule #codegenValuesEncoder(_BufferId:Identifier, e(HeadSize:SemanticsError), _AppendValues:NonEmptyStatementsOrError) => HeadSize - rule #encodeStatements(_BufferId:Identifier, v(_HeadSize:Expression), AppendValues:SemanticsError) + rule #codegenValuesEncoder(_BufferId:Identifier, v(_HeadSize:Expression), AppendValues:SemanticsError) => AppendValues - rule #encodeStatements(BufferId:Identifier, v(HeadSize:Expression), AppendValues:NonEmptyStatements) + rule #codegenValuesEncoder(BufferId:Identifier, v(HeadSize:Expression), AppendValues:NonEmptyStatements) => concatNonEmptyStatements ( let ulm#head_size = HeadSize; let ulm#head = :: bytes_hooks :: empty ( .CallParamsList ); diff --git a/ulm-semantics/main/encoding/syntax.md b/ulm-semantics/main/encoding/syntax.md index ab2d07de..d7688cb9 100644 --- a/ulm-semantics/main/encoding/syntax.md +++ b/ulm-semantics/main/encoding/syntax.md @@ -25,7 +25,7 @@ module ULM-ENCODING-SYNTAX syntax EncodeValues ::= List{EncodeValue, ","} // assumes that bufferId points to an empty buffer. - syntax NonEmptyStatementsOrError ::= encodeStatements(bufferId: Identifier, values: EncodeValues) [function, total] + syntax NonEmptyStatementsOrError ::= codegenValuesEncoder(bufferId: Identifier, values: EncodeValues) [function, total] syntax EncodeValue ::= paramToEncodeValue(NormalizedFunctionParameter) [function, total] syntax EncodeValues ::= paramsToEncodeValues(NormalizedFunctionParameterList) [function, total] diff --git a/ulm-semantics/main/preprocessing/endpoints.md b/ulm-semantics/main/preprocessing/endpoints.md index e4326892..1e4dda88 100644 --- a/ulm-semantics/main/preprocessing/endpoints.md +++ b/ulm-semantics/main/preprocessing/endpoints.md @@ -48,7 +48,7 @@ module ULM-PREPROCESSING-ENDPOINTS (... wrapperMethod: WrapperMethod , params: Params , method: ImplementationMethod - , appendReturn: encodeStatements(buffer_id, (return_value : ReturnType , .EncodeValues)) + , appendReturn: codegenValuesEncoder(buffer_id, (return_value : ReturnType , .EncodeValues)) , decodeStatements: decodeParams(0, Params) ) diff --git a/ulm-semantics/main/preprocessing/events.md b/ulm-semantics/main/preprocessing/events.md index d6e28088..1c4885ef 100644 --- a/ulm-semantics/main/preprocessing/events.md +++ b/ulm-semantics/main/preprocessing/events.md @@ -34,7 +34,7 @@ module ULM-PREPROCESSING-EVENTS // but the last one are indexed. We should handle generic events. => #ulmPreprocessEvent ( Method - , encodeStatements + , codegenValuesEncoder ( data , paramsToEncodeValues ( last(Param, Params) From 5f4b61d6a786ef974ce64b44a3f58dbc6764999c Mon Sep 17 00:00:00 2001 From: Virgil Date: Wed, 20 Nov 2024 15:17:40 +0200 Subject: [PATCH 08/10] Rename data to log_buffer --- ulm-semantics/main/preprocessing/events.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/ulm-semantics/main/preprocessing/events.md b/ulm-semantics/main/preprocessing/events.md index 1c4885ef..475a9029 100644 --- a/ulm-semantics/main/preprocessing/events.md +++ b/ulm-semantics/main/preprocessing/events.md @@ -8,7 +8,7 @@ module ULM-PREPROCESSING-EVENTS imports private ULM-PREPROCESSING-SYNTAX-PRIVATE syntax Identifier ::= "bytes_hooks" [token] - | "data" [token] + | "log_buffer" [token] | "empty" [token] | "Log0" [token] | "Log1" [token] @@ -35,7 +35,7 @@ module ULM-PREPROCESSING-EVENTS => #ulmPreprocessEvent ( Method , codegenValuesEncoder - ( data + ( log_buffer , paramsToEncodeValues ( last(Param, Params) , .NormalizedFunctionParameterList @@ -68,13 +68,13 @@ module ULM-PREPROCESSING-EVENTS empty => block({ .InnerAttributes concatNonEmptyStatements - ( let data = :: bytes_hooks :: empty ( .CallParamsList ); + ( let log_buffer = :: bytes_hooks :: empty ( .CallParamsList ); AppendLast , :: ulm :: LogIdentifier ( ptrValue(null, EventSignature) , concatCallParamsList ( paramsToArgs(allButLast(Param, Params)) - , (data , .CallParamsList) + , (log_buffer , .CallParamsList) ) ); .NonEmptyStatements From 65ac93ef194239f62bfea4c7fef88328fbb347ff Mon Sep 17 00:00:00 2001 From: Virgil Date: Wed, 20 Nov 2024 16:44:17 +0200 Subject: [PATCH 09/10] More documentation --- ulm-semantics/test/execution.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/ulm-semantics/test/execution.md b/ulm-semantics/test/execution.md index 2155f95f..7f22cbb2 100644 --- a/ulm-semantics/test/execution.md +++ b/ulm-semantics/test/execution.md @@ -179,6 +179,9 @@ module ULM-TEST-EXECUTION rule (ulmCancel ~> expect_cancel) => .K + // BytesList is used to define bytes concatenation in tests, so the "+" + // uses below represent the test AST concatenation, which we are + // evaluating by concatenating the bytes. syntax Bytes ::= concat(BytesList) [function, total] rule concat(.BytesList) => b"" rule concat(B:Bytes + Bs:BytesList) => B +Bytes concat(Bs) From d40e15de09cd43c2c29985698b2d9c787a8421a9 Mon Sep 17 00:00:00 2001 From: Virgil Date: Fri, 22 Nov 2024 19:30:58 +0200 Subject: [PATCH 10/10] Remove spaces --- tests/ulm-with-contract/types.str-raw.run | 18 +++++++++--------- tests/ulm-with-contract/types.str.run | 18 +++++++++--------- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/tests/ulm-with-contract/types.str-raw.run b/tests/ulm-with-contract/types.str-raw.run index 4e875994..a53a467c 100644 --- a/tests/ulm-with-contract/types.str-raw.run +++ b/tests/ulm-with-contract/types.str-raw.run @@ -1,18 +1,18 @@ -push "strEndpoint"; -hold_string_from_test_stack; -hold_list_values_from_test_stack; -hold_list_values_from_test_stack; -encode_call_data; +push "strEndpoint"; +hold_string_from_test_stack; +hold_list_values_from_test_stack; +hold_list_values_from_test_stack; +encode_call_data; -return_value; -mock CallData; +return_value; +mock CallData; call_contract 12345; return_value; check_eq (); -push_status; -check_eq 2; +push_status; +check_eq 2; check_raw_output b"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x20" + diff --git a/tests/ulm-with-contract/types.str.run b/tests/ulm-with-contract/types.str.run index b21c2243..384e17ac 100644 --- a/tests/ulm-with-contract/types.str.run +++ b/tests/ulm-with-contract/types.str.run @@ -1,18 +1,18 @@ -push "strEndpoint"; -hold_string_from_test_stack; -hold_list_values_from_test_stack; -hold_list_values_from_test_stack; -encode_call_data; +push "strEndpoint"; +hold_string_from_test_stack; +hold_list_values_from_test_stack; +hold_list_values_from_test_stack; +encode_call_data; -return_value; -mock CallData; +return_value; +mock CallData; call_contract 12345; return_value; check_eq (); -push_status; -check_eq 2; +push_status; +check_eq 2; output_to_arg; call :: test_helpers :: decode_single_str; return_value;