From 85e481adfa752da7016883d7ca1a6c7ee4591409 Mon Sep 17 00:00:00 2001
From: Virgil <25692529+virgil-serbanuta@users.noreply.github.com>
Date: Wed, 16 Oct 2024 14:34:59 +0300
Subject: [PATCH] Preprocess contracts (#152)
* Call endpoints
* Fix LLVM backend crash
---
Makefile | 55 ++++
.../main/preprocessing/configuration.md | 2 +-
rust-semantics/error.md | 20 +-
rust-semantics/expression/comparisons.md | 20 +-
rust-semantics/expression/struct.md | 4 +-
rust-semantics/helpers.md | 3 +
rust-semantics/preprocessing/configuration.md | 8 +-
rust-semantics/representation.md | 11 +-
rust-semantics/rust-common-syntax.md | 4 +-
rust-semantics/test/configuration.md | 1 +
rust-semantics/test/execution.md | 12 +
tests/ukm-contracts/bytes_hooks.rs | 2 +-
tests/ukm-contracts/state_hooks.rs | 4 +
tests/ukm-contracts/ukm.rs | 2 +-
tests/ukm-with-contract/endpoints.1.run | 23 ++
tests/ukm-with-contract/endpoints.rs | 23 ++
ukm-semantics/main/common-tools.md | 13 +
ukm-semantics/main/configuration.md | 3 +
ukm-semantics/main/execution.md | 6 +
ukm-semantics/main/execution/dispatch.md | 34 +++
ukm-semantics/main/execution/syntax.md | 2 +-
ukm-semantics/main/hooks.md | 4 +
ukm-semantics/main/hooks/bytes.md | 14 +-
ukm-semantics/main/hooks/state.md | 74 +++++
ukm-semantics/main/hooks/ukm.md | 20 ++
.../main/preprocessed-configuration.md | 7 +-
ukm-semantics/main/preprocessing.md | 11 +
.../main/preprocessing/configuration.md | 21 ++
ukm-semantics/main/preprocessing/crates.md | 14 +
ukm-semantics/main/preprocessing/endpoints.md | 282 ++++++++++++++++++
ukm-semantics/main/preprocessing/methods.md | 69 +++++
ukm-semantics/main/preprocessing/syntax.md | 35 +++
ukm-semantics/main/preprocessing/traits.md | 35 +++
ukm-semantics/main/representation.md | 18 ++
.../targets/execution/configuration.md | 2 +-
.../targets/preprocessing/configuration.md | 2 +
.../targets/testing/configuration.md | 4 +
ukm-semantics/test/execution.md | 52 ++++
38 files changed, 876 insertions(+), 40 deletions(-)
create mode 100644 tests/ukm-contracts/state_hooks.rs
create mode 100644 tests/ukm-with-contract/endpoints.1.run
create mode 100644 tests/ukm-with-contract/endpoints.rs
create mode 100644 ukm-semantics/main/common-tools.md
create mode 100644 ukm-semantics/main/execution/dispatch.md
create mode 100644 ukm-semantics/main/hooks/state.md
create mode 100644 ukm-semantics/main/hooks/ukm.md
create mode 100644 ukm-semantics/main/preprocessing/configuration.md
create mode 100644 ukm-semantics/main/preprocessing/crates.md
create mode 100644 ukm-semantics/main/preprocessing/endpoints.md
create mode 100644 ukm-semantics/main/preprocessing/methods.md
create mode 100644 ukm-semantics/main/preprocessing/traits.md
create mode 100644 ukm-semantics/main/representation.md
diff --git a/Makefile b/Makefile
index 3a1416b..e052e85 100644
--- a/Makefile
+++ b/Makefile
@@ -82,6 +82,11 @@ UKM_NO_CONTRACT_TESTING_OUTPUT_DIR ::= .build/ukm-no-contract/output
UKM_NO_CONTRACT_TESTING_INPUTS ::= $(wildcard $(UKM_NO_CONTRACT_TESTING_INPUT_DIR)/*.run)
UKM_NO_CONTRACT_TESTING_OUTPUTS ::= $(patsubst $(UKM_NO_CONTRACT_TESTING_INPUT_DIR)/%,$(UKM_NO_CONTRACT_TESTING_OUTPUT_DIR)/%.executed.kore,$(UKM_NO_CONTRACT_TESTING_INPUTS))
+UKM_WITH_CONTRACT_TESTING_INPUT_DIR ::= tests/ukm-with-contract
+UKM_WITH_CONTRACT_TESTING_OUTPUT_DIR ::= .build/ukm-with-contract/output
+UKM_WITH_CONTRACT_TESTING_INPUTS ::= $(wildcard $(UKM_WITH_CONTRACT_TESTING_INPUT_DIR)/*.run)
+UKM_WITH_CONTRACT_TESTING_OUTPUTS ::= $(patsubst $(UKM_WITH_CONTRACT_TESTING_INPUT_DIR)/%,$(UKM_WITH_CONTRACT_TESTING_OUTPUT_DIR)/%.executed.kore,$(UKM_WITH_CONTRACT_TESTING_INPUTS))
+
.PHONY: clean build build-legacy test test-legacy syntax-test preprocessing-test execution-test mx-test mx-rust-test mx-rust-contract-test mx-rust-two-contracts-test demos-test ukm-no-contracts-test
all: build test
@@ -127,6 +132,8 @@ demos-test: $(DEMOS_TESTING_OUTPUTS)
ukm-no-contracts-test: $(UKM_NO_CONTRACT_TESTING_OUTPUTS)
+ukm-with-contracts-test: $(UKM_WITH_CONTRACT_TESTING_OUTPUTS)
+
$(RUST_PREPROCESSING_TIMESTAMP): $(RUST_SEMANTICS_FILES)
# Workaround for https://github.com/runtimeverification/k/issues/4141
-rm -r $(RUST_PREPROCESSING_KOMPILED)
@@ -424,3 +431,51 @@ $(UKM_NO_CONTRACT_TESTING_OUTPUT_DIR)/%.run.executed.kore: \
-pTEST=$(CURDIR)/parsers/test-ukm-testing-execution.sh
cat $@.tmp | grep -q "Lbl'-LT-'k'-GT-'{}(dotk{}())"
mv -f $@.tmp $@
+
+
+# TODO: Add $(shell echo "$<" | sed 's/\.[^.]*.run$$//').rs
+# as a dependency
+$(UKM_WITH_CONTRACT_TESTING_OUTPUT_DIR)/%.run.executed.kore: \
+ $(UKM_WITH_CONTRACT_TESTING_INPUT_DIR)/%.run \
+ $(UKM_CONTRACTS_TESTING_INPUT_DIR)/bytes_hooks.rs \
+ $(UKM_CONTRACTS_TESTING_INPUT_DIR)/ukm.rs \
+ $(UKM_TESTING_TIMESTAMP) \
+ $(wildcard parsers/inc-*.sh) \
+ parsers/crates-ukm-testing-execution.sh \
+ parsers/test-ukm-testing-execution.sh
+ mkdir -p $(UKM_WITH_CONTRACT_TESTING_OUTPUT_DIR)
+
+ echo "<(<" > $@.in.tmp
+ echo "::bytes_hooks" >> $@.in.tmp
+ echo "<|>" >> $@.in.tmp
+ cat $(UKM_CONTRACTS_TESTING_INPUT_DIR)/bytes_hooks.rs >> $@.in.tmp
+ echo ">)>" >> $@.in.tmp
+
+ echo "<(<" >> $@.in.tmp
+ echo "::state_hooks" >> $@.in.tmp
+ echo "<|>" >> $@.in.tmp
+ cat $(UKM_CONTRACTS_TESTING_INPUT_DIR)/state_hooks.rs >> $@.in.tmp
+ echo ">)>" >> $@.in.tmp
+
+ echo "<(<" >> $@.in.tmp
+ echo "::ukm" >> $@.in.tmp
+ echo "<|>" >> $@.in.tmp
+ cat $(UKM_CONTRACTS_TESTING_INPUT_DIR)/ukm.rs >> $@.in.tmp
+ echo ">)>" >> $@.in.tmp
+
+ echo "<(<" >> $@.in.tmp
+ echo "$<" | sed 's%^.*/%%' | sed 's/\..*//' | sed 's/^/::/' >> $@.in.tmp
+ echo "<|>" >> $@.in.tmp
+ cat "$(shell echo "$<" | sed 's/\.[^.]*.run$$//').rs" >> $@.in.tmp
+ echo ">)>" >> $@.in.tmp
+
+ krun \
+ $@.in.tmp \
+ --parser $(CURDIR)/parsers/crates-ukm-testing-execution.sh \
+ --definition $(UKM_TESTING_KOMPILED) \
+ --output kore \
+ --output-file $@.tmp \
+ -cTEST='$(shell cat $<)' \
+ -pTEST=$(CURDIR)/parsers/test-ukm-testing-execution.sh
+ cat $@.tmp | grep -q "Lbl'-LT-'k'-GT-'{}(dotk{}())"
+ mv -f $@.tmp $@
diff --git a/mx-rust-semantics/main/preprocessing/configuration.md b/mx-rust-semantics/main/preprocessing/configuration.md
index 23fa448..6f724c5 100644
--- a/mx-rust-semantics/main/preprocessing/configuration.md
+++ b/mx-rust-semantics/main/preprocessing/configuration.md
@@ -17,7 +17,7 @@ module MX-RUST-PREPROCESSED-CONTRACT-TRAIT-CONFIGURATION
imports RUST-SHARED-SYNTAX
configuration
- (#token("no#path", "Identifier"):Identifier):TypePath // String to Identifier
+ (#token("no#path", "Identifier"):Identifier):TypePath
endmodule
module MX-RUST-PREPROCESSED-PROXIES-CONFIGURATION
diff --git a/rust-semantics/error.md b/rust-semantics/error.md
index 0f3f045..96ae836 100644
--- a/rust-semantics/error.md
+++ b/rust-semantics/error.md
@@ -5,6 +5,8 @@ module RUST-ERROR-SYNTAX
syntax ValueListOrError ::= concat(ValueOrError, ValueListOrError) [function, total]
syntax PtrListOrError ::= concat(Ptr, PtrListOrError) [function, total]
+ syntax StringOrError ::= concat(StringOrError, StringOrError) [function, total]
+ syntax NonEmptyStatementsOrError ::= concat(NonEmptyStatementsOrError, NonEmptyStatementsOrError) [function, total]
syntax PtrValueOrError ::= wrapPtrValueOrError(Ptr, ValueOrError) [function, total]
syntax TypePathOrError ::= doubleColonOrError(TypePathSegmentsOrError) [function, total]
syntax TypePathOrError ::= injectOrError(TypePathSegmentsOrError) [function, total]
@@ -22,10 +24,18 @@ module RUST-ERROR
rule concat(V:Value, L:ValueList) => V , L
rule concat(_:Value, E:SemanticsError) => E
rule concat(E:SemanticsError, _:ValueListOrError) => E
- rule concat(E:ValueOrError, L:ValueListOrError)
- => error("unexpected branch (concat(ValueOrError, ValueListOrError))", ListItem(E) ListItem(L))
+
+ rule concat(S1:String:StringOrError, S2:String:StringOrError) => S1 +String S2
+ rule concat(_:String:StringOrError, E:SemanticsError:StringOrError) => E
+ rule concat(E:SemanticsError:StringOrError, _:StringOrError) => E
+ rule concat(S1:StringOrError, S2:StringOrError)
+ => error("concat(StringOrError, StringOrError): Unknown error", ListItem(S1) ListItem(S2))
[owise]
+ rule concat(S1:NonEmptyStatements, S2:NonEmptyStatements) => concatNonEmptyStatements(S1, S2)
+ rule concat(_:NonEmptyStatements, E:SemanticsError) => E
+ rule concat(E:SemanticsError, _:NonEmptyStatementsOrError) => E
+
rule wrapPtrValueOrError(P:Ptr, V:Value) => ptrValue(P, V)
rule wrapPtrValueOrError(_:Ptr, E:SemanticsError) => E
@@ -38,9 +48,9 @@ module RUST-ERROR
rule concat(_:TypePathSegment, E) => E
rule concat(S:TypePathSegment, Ss:TypePathSegments) => S :: Ss
- rule andOrError(_:ExpressionOrError, E:SemanticsError) => E
- rule andOrError(E:SemanticsError, _:Expression) => E
- rule andOrError(E1:Expression, E2:Expression) => E1 && E2
+ rule andOrError(_:ExpressionOrError, e(E:SemanticsError)) => e(E)
+ rule andOrError(e(E:SemanticsError), v(_:Expression)) => e(E)
+ rule andOrError(v(E1:Expression), v(E2:Expression)) => v(E1 && E2)
rule tupleOrError(L:ValueList) => tuple(L)
rule tupleOrError(E:SemanticsError) => E
diff --git a/rust-semantics/expression/comparisons.md b/rust-semantics/expression/comparisons.md
index 4dc9e16..1c75f95 100644
--- a/rust-semantics/expression/comparisons.md
+++ b/rust-semantics/expression/comparisons.md
@@ -23,26 +23,28 @@ module RUST-EXPRESSION-STRUCT-COMPARISONS
rule (ptrValue(_, struct(StructName:TypePath, FirstFields:Map))
== ptrValue(_, struct(StructName, SecondFields:Map))
):Expression
- => allPtrEquality
- ( listToPtrList(values(FirstFields))
- , listToPtrList(values(SecondFields))
+ => unwrap
+ ( allPtrEquality
+ ( listToPtrList(values(FirstFields))
+ , listToPtrList(values(SecondFields))
+ )
)
[owise]
syntax ExpressionOrError ::= allPtrEquality(PtrListOrError, PtrListOrError)
[function, total]
- rule allPtrEquality(E:SemanticsError, _:PtrListOrError) => E
- rule allPtrEquality(_:PtrList, E:SemanticsError) => E
+ rule allPtrEquality(E:SemanticsError, _:PtrListOrError) => e(E)
+ rule allPtrEquality(_:PtrList, E:SemanticsError) => e(E)
- rule allPtrEquality(.PtrList, .PtrList) => true
+ rule allPtrEquality(.PtrList, .PtrList) => v(true)
rule allPtrEquality((P:Ptr , Ps:PtrList), (Q:Ptr , Qs:PtrList))
- => andOrError(P == Q , allPtrEquality(Ps, Qs))
+ => andOrError(v(P == Q) , allPtrEquality(Ps, Qs))
rule allPtrEquality(.PtrList, (_:Ptr , _:PtrList) #as Ps:PtrList)
- => error("allPtrEquality: Second list too long", ListItem(Ps))
+ => e(error("allPtrEquality: Second list too long", ListItem(Ps)))
rule allPtrEquality((_:Ptr , _:PtrList) #as Ps:PtrList, .PtrList)
- => error("zip(PtrList): First list too long", ListItem(Ps))
+ => e(error("zip(PtrList): First list too long", ListItem(Ps)))
endmodule
diff --git a/rust-semantics/expression/struct.md b/rust-semantics/expression/struct.md
index 7ac3b30..48242ec 100644
--- a/rust-semantics/expression/struct.md
+++ b/rust-semantics/expression/struct.md
@@ -57,9 +57,9 @@ module RUST-EXPRESSION-STRUCT
rule
fromStructExpressionWithAssignmentsBuildFieldsMap(
Name:TypePath,
- ((FieldName:Identifier : LE:Expression):StructExprField, RS):StructExprFields,
+ ((FieldName:Identifier : Le:Expression):StructExprField, RS):StructExprFields,
FieldsMap:Map)
- => LE ~> FieldName ~> fromStructExpressionWithAssignmentsBuildFieldsMap(Name, RS, FieldsMap)
+ => Le ~> FieldName ~> fromStructExpressionWithAssignmentsBuildFieldsMap(Name, RS, FieldsMap)
...
diff --git a/rust-semantics/helpers.md b/rust-semantics/helpers.md
index 884de7d..26a056f 100644
--- a/rust-semantics/helpers.md
+++ b/rust-semantics/helpers.md
@@ -42,5 +42,8 @@ module RUST-HELPERS
rule isSignedInt(u128) => true
rule isSignedInt(&T => T)
+ rule concatNonEmptyStatements(.NonEmptyStatements, S:NonEmptyStatements) => S
+ rule concatNonEmptyStatements(S:Statement Ss1:NonEmptyStatements, Ss2:NonEmptyStatements)
+ => S concatNonEmptyStatements(Ss1, Ss2)
endmodule
```
diff --git a/rust-semantics/preprocessing/configuration.md b/rust-semantics/preprocessing/configuration.md
index b82430a..78aeb23 100644
--- a/rust-semantics/preprocessing/configuration.md
+++ b/rust-semantics/preprocessing/configuration.md
@@ -4,8 +4,6 @@ module RUST-PREPROCESSING-CONFIGURATION
imports private RUST-REPRESENTATION
imports private RUST-SHARED-SYNTAX
- syntax Identifier ::= "my_identifier" [token]
-
configuration
@@ -17,7 +15,7 @@ module RUST-PREPROCESSING-CONFIGURATION
.List
- my_identifier:TypePath
+ #token("not#initialized", "Identifier"):Identifier:TypePath
.List // List of Identifier
@@ -30,14 +28,14 @@ module RUST-PREPROCESSING-CONFIGURATION
.List // List of TypePath
- my_identifier:TypePath
+ #token("not#initialized", "Identifier"):Identifier:TypePath
`emptyOuterAttributes`(.KList):OuterAttributes
.List // List of Identifier
- my_identifier:PathInExpression
+ #token("not#initialized", "Identifier"):Identifier:PathInExpression
.NormalizedFunctionParameterList
():Type
empty:FunctionBodyRepresentation
diff --git a/rust-semantics/representation.md b/rust-semantics/representation.md
index f4489b1..a4fe88d 100644
--- a/rust-semantics/representation.md
+++ b/rust-semantics/representation.md
@@ -98,7 +98,10 @@ module RUST-REPRESENTATION
syntax MapOrError ::= Map | SemanticsError
syntax Expression ::= Ptr
- syntax ExpressionOrError ::= Expression | SemanticsError
+ syntax ExpressionOrError ::= v(Expression) | e(SemanticsError)
+ syntax KItem ::= unwrap(ExpressionOrError) [function, total]
+ rule unwrap(v(E:Expression)) => E
+ rule unwrap(e(E:SemanticsError)) => E
syntax NormalizedFunctionParameterListOrError ::= NormalizedFunctionParameterList | SemanticsError
@@ -129,7 +132,10 @@ module RUST-REPRESENTATION
syntax IntOrError ::= valueToInteger(Value) [function, total]
syntax ValueOrError ::= integerToValue(Int, Type) [function, total]
+ syntax StringOrError ::= String | SemanticsError
+
syntax String ::= IdentifierToString(Identifier) [function, total, hook(STRING.token2string)]
+ syntax Identifier ::= StringToIdentifier(String) [function, total, hook(STRING.string2token)]
syntax CallParamsList ::= reverse(CallParamsList, CallParamsList) [function, total]
@@ -175,6 +181,9 @@ module RUST-REPRESENTATION
syntax TypePath ::= append(MaybeTypePath, Identifier) [function, total]
+ syntax NonEmptyStatementsOrError ::= NonEmptyStatements | SemanticsError
+ syntax NonEmptyStatements ::= concatNonEmptyStatements(NonEmptyStatements, NonEmptyStatements) [function, total]
+
endmodule
```
diff --git a/rust-semantics/rust-common-syntax.md b/rust-semantics/rust-common-syntax.md
index 7f86fb6..4f53038 100644
--- a/rust-semantics/rust-common-syntax.md
+++ b/rust-semantics/rust-common-syntax.md
@@ -197,8 +197,8 @@ https://doc.rust-lang.org/reference/items/extern-crates.html
syntax Struct ::= StructStruct | TupleStruct
syntax TupleStruct ::= "TODO: not needed yet, not implementing"
syntax StructStruct ::= "struct" Identifier MaybeGenericParams MaybeWhereClause "{" MaybeStructFields "}"
- syntax MaybeStructFields ::= "" | StructFields
- syntax StructFields ::= List{StructField, ","}
+ syntax MaybeStructFields ::= "" | StructFields | StructFields ","
+ syntax StructFields ::= NeList{StructField, ","}
syntax StructField ::= OuterAttributes MaybeVisibility Identifier ":" Type //TODO: Outerfields and visibility for
//struct fields is not yet supported.
diff --git a/rust-semantics/test/configuration.md b/rust-semantics/test/configuration.md
index 4126e0e..8c469cb 100644
--- a/rust-semantics/test/configuration.md
+++ b/rust-semantics/test/configuration.md
@@ -6,6 +6,7 @@ module RUST-EXECUTION-TEST-CONFIGURATION
configuration
.List
+ .Map
endmodule
diff --git a/rust-semantics/test/execution.md b/rust-semantics/test/execution.md
index e81ab94..5e71ed2 100644
--- a/rust-semantics/test/execution.md
+++ b/rust-semantics/test/execution.md
@@ -13,6 +13,7 @@ module RUST-EXECUTION-TEST-PARSING-SYNTAX
| "return_value_to_arg"
| "check_eq" Expression [strict]
| "push" Expression [strict]
+ syntax KItem ::= mock(KItem, K)
endmodule
module RUST-EXECUTION-TEST
@@ -92,6 +93,17 @@ module RUST-EXECUTION-TEST
VALUES:Map => VALUES[NVI <- V]
NVI:Int => NVI +Int 1
+ syntax KItem ::= wrappedK(K)
+ syntax Mockable
+
+ rule
+ mock(Mocked:Mockable, Result:K) => .K ...
+ M:Map => M[Mocked <- wrappedK(Result)]
+
+ rule
+ (Mocked:Mockable => Result) ...
+ Mocked |-> wrappedK(Result:K) ...
+ [priority(10)]
endmodule
```
\ No newline at end of file
diff --git a/tests/ukm-contracts/bytes_hooks.rs b/tests/ukm-contracts/bytes_hooks.rs
index 34d7fff..25d1ee1 100644
--- a/tests/ukm-contracts/bytes_hooks.rs
+++ b/tests/ukm-contracts/bytes_hooks.rs
@@ -6,7 +6,7 @@ extern "C" {
fn append_u64(bytes_id: u64, value: u64) -> u64;
fn append_u32(bytes_id: u64, value: u32) -> u64;
fn append_u16(bytes_id: u64, value: u16) -> u64;
- fn append_u7(bytes_id: u64, value: u8) -> u64;
+ fn append_u8(bytes_id: u64, value: u8) -> u64;
fn append_str(bytes_id: u64, value: &str) -> u64;
fn decode_u128(bytes_id: u64) -> (u64, u128);
diff --git a/tests/ukm-contracts/state_hooks.rs b/tests/ukm-contracts/state_hooks.rs
new file mode 100644
index 0000000..a563c28
--- /dev/null
+++ b/tests/ukm-contracts/state_hooks.rs
@@ -0,0 +1,4 @@
+extern "C" {
+ fn setStatus(status: u64);
+ fn setOutput(bytes_id: u64);
+}
diff --git a/tests/ukm-contracts/ukm.rs b/tests/ukm-contracts/ukm.rs
index ab78967..42ace10 100644
--- a/tests/ukm-contracts/ukm.rs
+++ b/tests/ukm-contracts/ukm.rs
@@ -1,7 +1,7 @@
#![no_std]
// TODO: Support structs and figure out the content of MessageResult
-struct MessageResult { }
+struct MessageResult { gas: u64 }
pub const EVMC_REJECTED: u64 = 0_u64;
pub const EVMC_INTERNAL_ERROR: u64 = 1_u64;
diff --git a/tests/ukm-with-contract/endpoints.1.run b/tests/ukm-with-contract/endpoints.1.run
new file mode 100644
index 0000000..7ed3553
--- /dev/null
+++ b/tests/ukm-with-contract/endpoints.1.run
@@ -0,0 +1,23 @@
+call :: bytes_hooks :: empty;
+return_value_to_arg;
+push "myEndpoint(Uint64)";
+call :: bytes_hooks :: append_str;
+return_value_to_arg;
+push 123_u64;
+call :: bytes_hooks :: append_u64;
+return_value;
+mock CallData;
+
+call_contract 12345;
+return_value;
+check_eq ();
+
+push_status;
+check_eq 2;
+
+output_to_arg;
+call :: endpoints :: decode_single_u64;
+return_value;
+
+check_eq 126_u64
+
diff --git a/tests/ukm-with-contract/endpoints.rs b/tests/ukm-with-contract/endpoints.rs
new file mode 100644
index 0000000..9fc6650
--- /dev/null
+++ b/tests/ukm-with-contract/endpoints.rs
@@ -0,0 +1,23 @@
+#![no_std]
+
+#[allow(unused_imports)]
+use ukm::*;
+
+#[ukm::contract]
+pub trait Endpoints {
+ #[init]
+ fn init(&self) {}
+
+ #[endpoint(myEndpoint)]
+ fn endpoint(&self, value: u64) -> u64 {
+ value + 3_u64
+ }
+}
+
+fn decode_single_u64(bytes_id: u64) -> u64 {
+ let (remaining_id, value) = :: bytes_hooks :: decode_u64(bytes_id);
+ if :: bytes_hooks :: length(remaining_id) > 0_u32 {
+ fail();
+ };
+ value
+}
diff --git a/ukm-semantics/main/common-tools.md b/ukm-semantics/main/common-tools.md
new file mode 100644
index 0000000..35cf524
--- /dev/null
+++ b/ukm-semantics/main/common-tools.md
@@ -0,0 +1,13 @@
+```k
+
+module UKM-COMMON-TOOLS-SYNTAX
+ syntax Identifier ::= "dispatcherMethodIdentifier" [function, total]
+endmodule
+
+module UKM-COMMON-TOOLS
+ imports private UKM-COMMON-TOOLS-SYNTAX
+
+ rule dispatcherMethodIdentifier => #token("ukm#dispatch#method", "Identifier")
+endmodule
+
+```
\ No newline at end of file
diff --git a/ukm-semantics/main/configuration.md b/ukm-semantics/main/configuration.md
index 73fefae..a065f34 100644
--- a/ukm-semantics/main/configuration.md
+++ b/ukm-semantics/main/configuration.md
@@ -1,12 +1,15 @@
```k
requires "hooks/bytes.md"
+requires "hooks/state.md"
module UKM-CONFIGURATION
imports UKM-HOOKS-BYTES-CONFIGURATION
+ imports UKM-HOOKS-STATE-CONFIGURATION
configuration
+
endmodule
diff --git a/ukm-semantics/main/execution.md b/ukm-semantics/main/execution.md
index 057de65..0b926d0 100644
--- a/ukm-semantics/main/execution.md
+++ b/ukm-semantics/main/execution.md
@@ -1,10 +1,16 @@
```k
+requires "common-tools.md"
+requires "execution/dispatch.md"
requires "execution/syntax.md"
requires "hooks.md"
+requires "representation.md"
module UKM-EXECUTION
+ imports private UKM-COMMON-TOOLS
+ imports private UKM-EXECUTION-DISPATCH
imports private UKM-HOOKS
+ imports private UKM-REPRESENTATION
endmodule
```
diff --git a/ukm-semantics/main/execution/dispatch.md b/ukm-semantics/main/execution/dispatch.md
new file mode 100644
index 0000000..f7e5743
--- /dev/null
+++ b/ukm-semantics/main/execution/dispatch.md
@@ -0,0 +1,34 @@
+```k
+
+module UKM-EXECUTION-DISPATCH
+ imports private COMMON-K-CELL
+ imports private RUST-REPRESENTATION
+ imports private RUST-VALUE-SYNTAX
+ imports private RUST-EXECUTION-CONFIGURATION
+ imports private UKM-COMMON-TOOLS-SYNTAX
+ imports private UKM-EXECUTION-SYNTAX
+ imports private UKM-PREPROCESSING-CONFIGURATION
+
+ syntax UkmInstruction ::= ukmExecute(contract:Value, gas: ValueOrError)
+
+ rule
+
+ ukmExecute(_AccountId:Int, Gas:Int)
+ => ukmExecute(struct(ContractTrait, .Map), integerToValue(Gas, u64))
+ ...
+
+
+ ContractTrait:TypePath
+
+ rule
+
+ ukmExecute(... contract: Contract:Value, gas: Gas:Value)
+ => ptr(NVI) . dispatcherMethodIdentifier ( ptrValue(null, Gas), .CallParamsList )
+ ...
+
+ Values:Map => Values[NVI <- Contract]
+ NVI:Int => NVI +Int 1
+ requires notBool NVI in_keys(Values)
+endmodule
+
+```
diff --git a/ukm-semantics/main/execution/syntax.md b/ukm-semantics/main/execution/syntax.md
index 54c919c..52b1158 100644
--- a/ukm-semantics/main/execution/syntax.md
+++ b/ukm-semantics/main/execution/syntax.md
@@ -3,7 +3,7 @@
module UKM-EXECUTION-SYNTAX
imports INT-SYNTAX
- syntax UKMInstruction ::= ukmExecute(accountId : Int)
+ syntax UKMInstruction ::= ukmExecute(accountId: Int, gas: Int)
endmodule
diff --git a/ukm-semantics/main/hooks.md b/ukm-semantics/main/hooks.md
index 3c55c44..95a0efd 100644
--- a/ukm-semantics/main/hooks.md
+++ b/ukm-semantics/main/hooks.md
@@ -1,9 +1,13 @@
```k
requires "hooks/bytes.md"
+requires "hooks/state.md"
+requires "hooks/ukm.md"
module UKM-HOOKS
imports private UKM-HOOKS-BYTES
+ imports private UKM-HOOKS-STATE
+ imports private UKM-HOOKS-UKM
endmodule
```
diff --git a/ukm-semantics/main/hooks/bytes.md b/ukm-semantics/main/hooks/bytes.md
index bd202c8..bf6acd3 100644
--- a/ukm-semantics/main/hooks/bytes.md
+++ b/ukm-semantics/main/hooks/bytes.md
@@ -15,12 +15,20 @@ module UKM-HOOKS-BYTES-CONFIGURATION
endmodule
+module UKM-HOOKS-BYTES-SYNTAX
+ imports BYTES-SYNTAX
+ syntax Expression ::= ukmBytesNew(Bytes)
+endmodule
+
module UKM-HOOKS-BYTES
imports private BYTES
imports private COMMON-K-CELL
imports private RUST-HELPERS
imports private RUST-REPRESENTATION
imports private UKM-HOOKS-BYTES-CONFIGURATION
+ imports private UKM-HOOKS-BYTES-SYNTAX
+ imports private UKM-REPRESENTATION
+
syntax Identifier ::= "bytes_hooks" [token]
| "empty" [token]
@@ -38,11 +46,6 @@ module UKM-HOOKS-BYTES
| "decode_u8" [token]
| "decode_str" [token]
- syntax UkmBytesValue ::= ukmBytesValue(Bytes)
- syntax UkmExpression ::= ukmBytesId(MInt{64})
- | UkmBytesValue
- syntax KResult ::= UkmBytesValue
-
rule
normalizedFunctionCall
@@ -175,7 +178,6 @@ module UKM-HOOKS-BYTES
| ukmBytesDecode(Int, Bytes, Type)
| ukmBytesDecodeInt(Int, Bytes, Type)
| ukmBytesDecode(ValueOrError, Bytes)
- syntax Expression ::= ukmBytesNew(Bytes)
rule
diff --git a/ukm-semantics/main/hooks/state.md b/ukm-semantics/main/hooks/state.md
new file mode 100644
index 0000000..ef50a11
--- /dev/null
+++ b/ukm-semantics/main/hooks/state.md
@@ -0,0 +1,74 @@
+```k
+
+module UKM-HOOKS-STATE-CONFIGURATION
+ imports BYTES-SYNTAX
+ imports INT-SYNTAX
+
+ configuration
+
+ 0
+ b""
+ 0
+
+endmodule
+
+module UKM-HOOKS-STATE
+ imports private COMMON-K-CELL
+ imports private RUST-REPRESENTATION
+ imports private RUST-SHARED-SYNTAX
+ imports private UKM-HOOKS-STATE-CONFIGURATION
+ imports private UKM-REPRESENTATION
+
+ syntax UKMInstruction ::= ukmSetStatus(Expression) [strict(1)]
+ | ukmSetGasLeft(Expression) [strict(1)]
+ | ukmSetOutput(Expression) [strict(1)]
+ | ukmSetOutput(UkmExpression) [strict(1)]
+
+ syntax Identifier ::= "state_hooks" [token]
+ | "setStatus" [token]
+ | "setGasLeft" [token]
+ | "setOutput" [token]
+
+ rule normalizedFunctionCall
+ ( :: state_hooks :: setStatus :: .PathExprSegments
+ , StatusId:Ptr , .PtrList
+ )
+ => ukmSetStatus(StatusId)
+
+ rule normalizedFunctionCall
+ ( :: state_hooks :: setGasLeft :: .PathExprSegments
+ , GasId:Ptr , .PtrList
+ )
+ => ukmSetGasLeft(GasId)
+
+ rule normalizedFunctionCall
+ ( :: state_hooks :: setOutput :: .PathExprSegments
+ , OutputId:Ptr , .PtrList
+ )
+ => ukmSetOutput(OutputId)
+
+ rule
+
+ ukmSetStatus(ptrValue(_, u64(Value))) => ptrValue(null, tuple(.ValueList))
+ ...
+
+ _ => MInt2Unsigned(Value)
+
+ rule
+
+ ukmSetGasLeft(ptrValue(_, u64(Value))) => ptrValue(null, tuple(.ValueList))
+ ...
+
+ _ => MInt2Unsigned(Value)
+
+ rule ukmSetOutput(ptrValue(_, u64(BytesId))) => ukmSetOutput(ukmBytesId(BytesId))
+ rule
+
+ ukmSetOutput(ukmBytesValue(Value:Bytes)) => ptrValue(null, tuple(.ValueList))
+ ...
+
+ _ => Value
+
+endmodule
+
+```
diff --git a/ukm-semantics/main/hooks/ukm.md b/ukm-semantics/main/hooks/ukm.md
new file mode 100644
index 0000000..b6d2a41
--- /dev/null
+++ b/ukm-semantics/main/hooks/ukm.md
@@ -0,0 +1,20 @@
+```k
+
+module UKM-HOOKS-UKM-SYNTAX
+ syntax UkmHook ::= CallDataHook()
+endmodule
+
+
+module UKM-HOOKS-UKM
+ imports private RUST-REPRESENTATION
+ imports private RUST-SHARED-SYNTAX
+ imports private UKM-HOOKS-UKM-SYNTAX
+
+ syntax Identifier ::= "ukm" [token]
+ | "CallData" [token]
+
+ rule normalizedFunctionCall ( ukm :: CallData :: .PathExprSegments , .PtrList )
+ => CallDataHook()
+endmodule
+
+```
diff --git a/ukm-semantics/main/preprocessed-configuration.md b/ukm-semantics/main/preprocessed-configuration.md
index 6b12cb0..a9e2d93 100644
--- a/ukm-semantics/main/preprocessed-configuration.md
+++ b/ukm-semantics/main/preprocessed-configuration.md
@@ -1,13 +1,10 @@
```k
-module UKM-PREPROCESSED-CONFIGURATION
- configuration
- .K
-endmodule
+requires "preprocessing/configuration.md"
module UKM-FULL-PREPROCESSED-CONFIGURATION
imports RUST-PREPROCESSING-CONFIGURATION
- imports UKM-PREPROCESSED-CONFIGURATION
+ imports UKM-PREPROCESSING-CONFIGURATION
configuration
diff --git a/ukm-semantics/main/preprocessing.md b/ukm-semantics/main/preprocessing.md
index ebcd71d..46645bc 100644
--- a/ukm-semantics/main/preprocessing.md
+++ b/ukm-semantics/main/preprocessing.md
@@ -1,8 +1,19 @@
```k
+requires "preprocessing/crates.md"
+requires "preprocessing/endpoints.md"
+requires "preprocessing/methods.md"
requires "preprocessing/syntax.md"
+requires "preprocessing/traits.md"
+requires "common-tools.md"
+requires "representation.md"
module UKM-PREPROCESSING
+ imports private UKM-COMMON-TOOLS
+ imports private UKM-PREPROCESSING-CRATES
+ imports private UKM-PREPROCESSING-ENDPOINTS
+ imports private UKM-PREPROCESSING-METHODS
+ imports private UKM-PREPROCESSING-TRAITS
endmodule
```
diff --git a/ukm-semantics/main/preprocessing/configuration.md b/ukm-semantics/main/preprocessing/configuration.md
new file mode 100644
index 0000000..9302083
--- /dev/null
+++ b/ukm-semantics/main/preprocessing/configuration.md
@@ -0,0 +1,21 @@
+```k
+
+module UKM-PREPROCESSING-CONFIGURATION
+ imports RUST-SHARED-SYNTAX
+
+ configuration
+
+
+ (#token("not#initialized", "Identifier"):Identifier):TypePath
+
+
+endmodule
+
+module UKM-PREPROCESSING-EPHEMERAL-CONFIGURATION
+ configuration
+
+ .Map
+
+endmodule
+
+```
diff --git a/ukm-semantics/main/preprocessing/crates.md b/ukm-semantics/main/preprocessing/crates.md
new file mode 100644
index 0000000..1f8e44d
--- /dev/null
+++ b/ukm-semantics/main/preprocessing/crates.md
@@ -0,0 +1,14 @@
+```k
+
+module UKM-PREPROCESSING-CRATES
+ imports private COMMON-K-CELL
+ imports private RUST-PREPROCESSING-CONFIGURATION
+ imports private UKM-PREPROCESSING-SYNTAX
+ imports private UKM-PREPROCESSING-SYNTAX-PRIVATE
+
+ rule
+ ukmPreprocessCrates => ukmPreprocessTraits(Traits) ...
+ Traits:List
+endmodule
+
+```
diff --git a/ukm-semantics/main/preprocessing/endpoints.md b/ukm-semantics/main/preprocessing/endpoints.md
new file mode 100644
index 0000000..b97b986
--- /dev/null
+++ b/ukm-semantics/main/preprocessing/endpoints.md
@@ -0,0 +1,282 @@
+```k
+
+module UKM-PREPROCESSING-ENDPOINTS
+ imports private COMMON-K-CELL
+ imports private RUST-CONVERSIONS-SYNTAX
+ imports private RUST-ERROR-SYNTAX
+ imports private RUST-PREPROCESSING-CONFIGURATION
+ imports private RUST-SHARED-SYNTAX
+ imports private UKM-COMMON-TOOLS-SYNTAX
+ imports private UKM-PREPROCESSING-EPHEMERAL-CONFIGURATION
+ imports private UKM-PREPROCESSING-SYNTAX-PRIVATE
+
+ rule
+
+ ukmPreprocessEndpoint
+ ( Trait:TypePath
+ , Method:Identifier
+ , FullMethodPath:PathInExpression
+ , Name:String
+ )
+ => ukmAddEndpointWrapper
+ ( typePathToPathInExpression(append(Trait, StringToIdentifier("ukmWrap#" +String Name)))
+ , Params
+ , ReturnType
+ , Method
+ )
+ ~> ukmAddEndpointSignature
+ ( methodSignature(Name, Params)
+ , StringToIdentifier("ukmWrap#" +String Name)
+ )
+ ...
+
+ FullMethodPath
+ (self : $selftype , Params:NormalizedFunctionParameterList)
+ ReturnType:Type
+
+
+ rule ukmAddEndpointWrapper
+ (... wrapperMethod: WrapperMethod:PathInExpression
+ , params: Params:NormalizedFunctionParameterList
+ , returnType: ReturnType:Type
+ , method: ImplementationMethod:Identifier
+ )
+ => #ukmAddEndpointWrapper
+ (... wrapperMethod: WrapperMethod
+ , params: Params
+ , method: ImplementationMethod
+ , appendReturn: appendValue(buffer_id, return_value, ReturnType)
+ , decodeStatements: decodeParams(0, Params)
+ )
+
+ rule
+
+ #ukmAddEndpointWrapper
+ (... wrapperMethod: WrapperMethod:PathInExpression
+ , params: Params:NormalizedFunctionParameterList
+ , method: ImplementationMethod:Identifier
+ , appendReturn: v(Append:Expression)
+ , decodeStatements: Decode:NonEmptyStatements
+ ) => .K
+ ...
+
+
+ (.Bag =>
+
+ WrapperMethod
+
+ self : $selftype , buffer_id : u64 , gas : u64 , .NormalizedFunctionParameterList
+
+ ():Type
+
+ block({
+ .InnerAttributes
+ :: 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(:: ukm :: EVMC_SUCCESS , .CallParamsList);
+ )
+ })
+
+ `emptyOuterAttributes`(.KList)
+
+ )
+ ...
+
+
+ rule
+
+ ukmAddEndpointSignature(Signature:String, Method:Identifier) => .K
+ ...
+
+
+ Signatures:Map => Signatures[Signature <- Method]
+
+ requires notBool (Signature in_keys(Signatures))
+
+
+ rule
+
+ ukmAddDispatcher(TypePath) => .K
+ ...
+
+
+ Signatures:Map
+
+
+ (.Bag =>
+
+
+ typePathToPathInExpression(append(TypePath, dispatcherMethodIdentifier))
+
+
+ self : $selftype , gas : u64, .NormalizedFunctionParameterList
+
+ ():Type
+
+ block({
+ .InnerAttributes
+ concatNonEmptyStatements
+ ( let buffer_id = ukm :: CallData();
+ let ( buffer_id | .PatternNoTopAlts
+ , signature | .PatternNoTopAlts
+ , .Patterns
+ ) = decodeSignature(buffer_id);
+ .NonEmptyStatements
+ , signatureToCall(signature, keys_list(Signatures), Signatures, buffer_id, gas)
+ .NonEmptyStatements
+ )
+ })
+
+ `emptyOuterAttributes`(.KList)
+
+ )
+ ...
+
+
+ syntax Identifier ::= "buffer_id" [token]
+ | "signature" [token]
+ | "gas" [token]
+ | "state_hooks" [token]
+ | "setGasLeft" [token]
+ | "setOutput" [token]
+ | "setStatus" [token]
+ | "return_value" [token]
+ | "bytes_hooks" [token]
+ | "append_u8" [token]
+ | "append_u16" [token]
+ | "append_u32" [token]
+ | "append_u64" [token]
+ | "decode_u8" [token]
+ | "decode_u16" [token]
+ | "decode_u32" [token]
+ | "decode_u64" [token]
+ | "decode_str" [token]
+ | "empty" [token]
+ | "ukm" [token]
+ | "CallData" [token]
+ | "EVMC_BAD_JUMP_DESTINATION" [token]
+ | "EVMC_SUCCESS" [token]
+
+ syntax StringOrError ::= methodSignature(String, NormalizedFunctionParameterList) [function, total]
+ | signatureTypes(NormalizedFunctionParameterList) [function, total]
+ | signatureType(Type) [function, total]
+
+ rule methodSignature(S:String, Ps:NormalizedFunctionParameterList)
+ => concat(concat(S +String "(", signatureTypes(Ps)), ")")
+
+ rule signatureTypes(.NormalizedFunctionParameterList) => ""
+ rule signatureTypes(_ : T:Type , .NormalizedFunctionParameterList)
+ => signatureType(T)
+ rule signatureTypes
+ ( _ : T:Type
+ , ((_:NormalizedFunctionParameter , _:NormalizedFunctionParameterList)
+ #as Ps:NormalizedFunctionParameterList)
+ )
+ => concat(signatureType(T), concat(",", signatureTypes(Ps)))
+
+ rule signatureType(u8) => "Uint8"
+ rule signatureType(u16) => "Uint16"
+ rule signatureType(u32) => "Uint32"
+ rule signatureType(u64) => "Uint64"
+ rule signatureType(T) => error("Unknown type in signatureType:", ListItem(T))
+ [owise]
+
+ syntax Statement ::= signatureToCall
+ ( signature: Identifier
+ , signatures: List
+ , signatureToMethod: Map
+ , bufferId: Identifier
+ , gas: Identifier
+ ) [function, total]
+ rule signatureToCall
+ (... signature: _:Identifier
+ , signatures: .List
+ , signatureToMethod: _:Map
+ , bufferId: _:Identifier
+ , gas: _:Identifier
+ )
+ // TODO: Is this the right kind of error?
+ => :: state_hooks :: setStatus(:: ukm :: EVMC_BAD_JUMP_DESTINATION , .CallParamsList);
+
+ rule signatureToCall
+ (... signature: Signature:Identifier
+ , signatures: ListItem(CurrentSignature:String) Signatures:List
+ , signatureToMethod: (CurrentSignature |-> Method:Identifier _:Map) #as SignatureToMethod:Map
+ , bufferId: BufferId:Identifier
+ , gas: Gas:Identifier
+ )
+ => if signature == CurrentSignature {
+ .InnerAttributes
+ self . Method ( BufferId , Gas , .CallParamsList );
+ .NonEmptyStatements
+ } else {
+ .InnerAttributes
+ signatureToCall(Signature, Signatures, SignatureToMethod, BufferId, Gas)
+ .NonEmptyStatements
+ };
+
+ syntax Expression ::= decodeSignature(Identifier) [function, total]
+ rule decodeSignature(BufferId) => :: bytes_hooks :: decode_str ( BufferId , .CallParamsList )
+
+ syntax ExpressionOrError ::= appendValue(bufferId: Identifier, value: Identifier, Type) [function, total]
+ 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, ()) => v(BufferId)
+ rule appendValue(BufferId:Identifier, Value:Identifier, T:Type)
+ => e(error("appendValue: unrecognized type", ListItem(BufferId) ListItem(Value) ListItem(T)))
+ [owise]
+
+ syntax NonEmptyStatementsOrError ::= decodeParams(Int, NormalizedFunctionParameterList) [function, total]
+ rule decodeParams(_:Int, .NormalizedFunctionParameterList) => .NonEmptyStatements
+ rule decodeParams(Index:Int, _ : T:Type , Ps:NormalizedFunctionParameterList)
+ => concat(decodeParam(Index, T), decodeParams(Index +Int 1, Ps))
+
+ syntax NonEmptyStatementsOrError ::= decodeParam(Int, Type) [function, total]
+ syntax NonEmptyStatementsOrError ::= decodeParam(Int, ExpressionOrError) [function, total]
+ syntax ExpressionOrError ::= decodeForType(Type) [function, total]
+ rule decodeParam(I:Int, T:Type) => decodeParam(I, decodeForType(T))
+ rule decodeParam(_:Int, e(E:SemanticsError)) => E
+ rule decodeParam(Index:Int, v(E:Expression))
+ => let ( buffer_id | .PatternNoTopAlts
+ , StringToIdentifier("v" +String Int2String(Index)) | .PatternNoTopAlts
+ , .Patterns
+ ) = E;
+ .NonEmptyStatements
+
+ rule decodeForType(T:Type) => e(error("decodeForType: unrecognized type", ListItem(T)))
+ [owise]
+ rule decodeForType(u8) => v(:: bytes_hooks :: decode_u8 ( buffer_id , .CallParamsList ))
+ rule decodeForType(u16) => v(:: bytes_hooks :: decode_u16 ( buffer_id , .CallParamsList ))
+ rule decodeForType(u32) => v(:: bytes_hooks :: decode_u32 ( buffer_id , .CallParamsList ))
+ rule decodeForType(u64) => v(:: bytes_hooks :: decode_u64 ( buffer_id , .CallParamsList ))
+
+ syntax Expression ::= callMethod(Identifier, NormalizedFunctionParameterList) [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))
+
+ rule callMethod(Method:Identifier, .CallParamsList)
+ => self . Method ( )
+ rule callMethod(Method:Identifier, (_ , _:CallParamsList) #as Ps:CallParamsList)
+ => self . Method ( Ps )
+
+ rule buildArgs(_:Int, .NormalizedFunctionParameterList) => .CallParamsList
+ rule buildArgs(Index:Int, _:NormalizedFunctionParameter , Ps:NormalizedFunctionParameterList)
+ => StringToIdentifier("v" +String Int2String(Index)) , buildArgs(Index +Int 1, Ps)
+
+endmodule
+
+```
diff --git a/ukm-semantics/main/preprocessing/methods.md b/ukm-semantics/main/preprocessing/methods.md
new file mode 100644
index 0000000..4a27f90
--- /dev/null
+++ b/ukm-semantics/main/preprocessing/methods.md
@@ -0,0 +1,69 @@
+```k
+
+module UKM-PREPROCESSING-METHODS
+ imports private COMMON-K-CELL
+ imports private K-EQUAL-SYNTAX
+ imports private RUST-CONVERSIONS-SYNTAX
+ imports private RUST-PREPROCESSING-CONFIGURATION
+ imports private UKM-PREPROCESSING-SYNTAX-PRIVATE
+
+ rule ukmPreprocessMethods(_:TypePath, .List) => .K
+ rule ukmPreprocessMethods(Trait:TypePath, ListItem(Name:Identifier) Methods:List)
+ => ukmPreprocessMethod(Trait, Name, typePathToPathInExpression(append(Trait, Name)))
+ ~> ukmPreprocessMethods(Trait, Methods:List)
+
+ rule
+
+ ukmPreprocessMethod(Trait:TypePath, MethodIdentifier:Identifier, Method:PathInExpression)
+ => ukmPreprocessEndpoint
+ (... trait: Trait
+ , method: MethodIdentifier
+ , fullMethodPath: Method
+ , endpointName: getEndpointName(Atts, MethodIdentifier)
+ )
+ ...
+
+ Method
+ Atts:OuterAttributes
+ requires getEndpointName(Atts, MethodIdentifier) =/=K ""
+ [priority(50)]
+ rule ukmPreprocessMethod(_:TypePath, _:Identifier, _:PathInExpression) => .K
+ [owise]
+
+ // This is identical to the function in the mx-rust semantics.
+ syntax String ::= getEndpointName(atts:OuterAttributes, default:Identifier) [function, total]
+ rule getEndpointName(, _:Identifier) => ""
+ rule getEndpointName(.NonEmptyOuterAttributes, _:Identifier) => ""
+ rule getEndpointName
+ ( (#[ #token("init", "Identifier") :: .SimplePathList
+ ])
+ _:NonEmptyOuterAttributes
+ , _:Identifier
+ ) => "#init"
+ rule getEndpointName
+ ( (#[ #token("upgrade", "Identifier") :: .SimplePathList
+ ])
+ _:NonEmptyOuterAttributes
+ , _:Identifier
+ ) => "#upgrade"
+ rule getEndpointName
+ ( (#[ #token("endpoint", "Identifier") :: .SimplePathList
+ ( Name:Identifier :: .PathExprSegments, .CallParamsList )
+ ])
+ _:NonEmptyOuterAttributes
+ , _:Identifier
+ ) => IdentifierToString(Name)
+ rule getEndpointName
+ ( (#[ #token("view", "Identifier") :: .SimplePathList
+ ( Name:Identifier :: .PathExprSegments, .CallParamsList )
+ ])
+ _:NonEmptyOuterAttributes
+ , _:Identifier
+ ) => IdentifierToString(Name)
+ rule getEndpointName(_:OuterAttribute Atts:NonEmptyOuterAttributes, Default:Identifier)
+ => getEndpointName(Atts, Default)
+ [owise]
+
+endmodule
+
+```
diff --git a/ukm-semantics/main/preprocessing/syntax.md b/ukm-semantics/main/preprocessing/syntax.md
index 1f2e8c9..eeb8a62 100644
--- a/ukm-semantics/main/preprocessing/syntax.md
+++ b/ukm-semantics/main/preprocessing/syntax.md
@@ -1,7 +1,42 @@
```k
module UKM-PREPROCESSING-SYNTAX
+ imports INT-SYNTAX
+
syntax UKMInstruction ::= "ukmPreprocessCrates"
endmodule
+module UKM-PREPROCESSING-SYNTAX-PRIVATE
+ imports LIST
+ imports RUST-REPRESENTATION
+ imports RUST-SHARED-SYNTAX
+
+ syntax UKMInstruction ::= ukmPreprocessTraits(List)
+ | ukmPreprocessTrait(TypePath)
+ | ukmPreprocessMethods(trait: TypePath, List)
+ | ukmPreprocessMethod(trait: TypePath, methodId: Identifier, fullMethodPath: PathInExpression)
+ | ukmPreprocessEndpoint
+ ( trait: TypePath
+ , method: Identifier
+ , fullMethodPath: PathInExpression
+ , endpointName: String
+ )
+ | ukmAddEndpointWrapper
+ ( wrapperMethod: PathInExpression
+ , params: NormalizedFunctionParameterList
+ , returnType: Type
+ , method: Identifier
+ )
+ | #ukmAddEndpointWrapper
+ ( wrapperMethod: PathInExpression
+ , params: NormalizedFunctionParameterList
+ , method: Identifier
+ , appendReturn: ExpressionOrError
+ , decodeStatements: NonEmptyStatementsOrError
+ )
+ | ukmAddEndpointSignature(signature: StringOrError, method: Identifier)
+ | ukmAddDispatcher(TypePath)
+
+endmodule
+
```
diff --git a/ukm-semantics/main/preprocessing/traits.md b/ukm-semantics/main/preprocessing/traits.md
new file mode 100644
index 0000000..2f1bcd0
--- /dev/null
+++ b/ukm-semantics/main/preprocessing/traits.md
@@ -0,0 +1,35 @@
+```k
+
+module UKM-PREPROCESSING-TRAITS
+ imports private COMMON-K-CELL
+ imports private RUST-PREPROCESSING-CONFIGURATION
+ imports private UKM-PREPROCESSING-CONFIGURATION
+ imports private UKM-PREPROCESSING-SYNTAX-PRIVATE
+
+ rule ukmPreprocessTraits(.List) => .K
+ rule ukmPreprocessTraits(ListItem(T:TypePath) Traits:List)
+ => ukmPreprocessTrait(T) ~> ukmPreprocessTraits(Traits)
+
+ rule
+
+ ukmPreprocessTrait(Trait:TypePath)
+ => ukmPreprocessMethods(Trait, Methods) ~> ukmAddDispatcher(Trait)
+ ...
+
+ Trait
+
+ #[ #token("ukm", "Identifier")
+ :: #token("contract", "Identifier")
+ :: .SimplePathList
+ ]
+ .NonEmptyOuterAttributes
+
+ Methods:List
+ _ => Trait
+
+ // There should be an owise rule rewriting ukmPreprocessTrait(_) to .K
+ // For now, it is probably more useful to stop execution when encountering
+ // an unknown trait than skipping it.
+endmodule
+
+```
diff --git a/ukm-semantics/main/representation.md b/ukm-semantics/main/representation.md
new file mode 100644
index 0000000..7de5054
--- /dev/null
+++ b/ukm-semantics/main/representation.md
@@ -0,0 +1,18 @@
+```k
+
+module UKM-REPRESENTATION
+ imports private BYTES-SYNTAX
+ imports private INT-SYNTAX
+ imports private MINT
+ imports private RUST-VALUE-SYNTAX
+
+ syntax UkmValue ::= ukmBytesValue(Bytes)
+ | ukmIntValue(Int)
+ syntax UkmExpression ::= ukmBytesId(MInt{64})
+ | ukmInt(MInt{64})
+ | UkmValue
+ syntax KResult ::= UkmValue
+
+endmodule
+
+```
diff --git a/ukm-semantics/targets/execution/configuration.md b/ukm-semantics/targets/execution/configuration.md
index d81dc0b..c5d7b08 100644
--- a/ukm-semantics/targets/execution/configuration.md
+++ b/ukm-semantics/targets/execution/configuration.md
@@ -13,7 +13,7 @@ module COMMON-K-CELL
configuration
ukmDecodePreprocessedCell($PGM:Bytes)
- ~> ukmExecute($ACCTCODE:Int)
+ ~> ukmExecute($ACCTCODE:Int, $GAS:Int)
endmodule
diff --git a/ukm-semantics/targets/preprocessing/configuration.md b/ukm-semantics/targets/preprocessing/configuration.md
index 020fe21..117bd71 100644
--- a/ukm-semantics/targets/preprocessing/configuration.md
+++ b/ukm-semantics/targets/preprocessing/configuration.md
@@ -22,10 +22,12 @@ endmodule
module UKM-TARGET-CONFIGURATION
imports COMMON-K-CELL
imports UKM-FULL-PREPROCESSED-CONFIGURATION
+ imports UKM-PREPROCESSING-EPHEMERAL-CONFIGURATION
configuration
+
endmodule
diff --git a/ukm-semantics/targets/testing/configuration.md b/ukm-semantics/targets/testing/configuration.md
index 84c1fc9..7d3a7c8 100644
--- a/ukm-semantics/targets/testing/configuration.md
+++ b/ukm-semantics/targets/testing/configuration.md
@@ -9,10 +9,12 @@ requires "rust-semantics/test/configuration.md"
module COMMON-K-CELL
imports private RUST-EXECUTION-TEST-PARSING-SYNTAX
imports private RUST-PREPROCESSING-SYNTAX
+ imports private UKM-PREPROCESSING-SYNTAX
configuration
cratesParser($PGM:WrappedCrateList)
+ ~> ukmPreprocessCrates
~> $TEST:ExecutionTest
endmodule
@@ -23,11 +25,13 @@ module UKM-TARGET-CONFIGURATION
imports RUST-EXECUTION-TEST-CONFIGURATION
imports UKM-CONFIGURATION
imports UKM-FULL-PREPROCESSED-CONFIGURATION
+ imports UKM-PREPROCESSING-EPHEMERAL-CONFIGURATION
imports UKM-TEST-CONFIGURATION
configuration
+
diff --git a/ukm-semantics/test/execution.md b/ukm-semantics/test/execution.md
index e3bc92e..b407c07 100644
--- a/ukm-semantics/test/execution.md
+++ b/ukm-semantics/test/execution.md
@@ -1,10 +1,62 @@
```k
module UKM-TEST-SYNTAX
+ imports INT-SYNTAX
imports RUST-EXECUTION-TEST-PARSING-SYNTAX
+
+ syntax ExecutionItem ::= "mock" "CallData"
+ | "call_contract" Int
+ | "output_to_arg"
+ | "push_status"
+ | "check_eq" Int
endmodule
module UKM-TEST-EXECUTION
+ imports private COMMON-K-CELL
+ imports private RUST-EXECUTION-TEST-CONFIGURATION
+ imports private UKM-EXECUTION-SYNTAX
+ imports private UKM-HOOKS-BYTES-CONFIGURATION
+ imports private UKM-HOOKS-BYTES-SYNTAX
+ imports private UKM-HOOKS-STATE-CONFIGURATION
+ imports private UKM-HOOKS-UKM-SYNTAX
+ imports private UKM-TEST-SYNTAX
+
+ syntax Mockable ::= UkmHook
+
+ rule
+ mock CallData => mock(CallDataHook(), V) ...
+
+ (ListItem(ptrValue(_, u64(_BytesId)) #as V:PtrValue) => .List)
+ ...
+
+
+ rule call_contract Account => ukmExecute(Account, 100)
+
+ rule
+
+ output_to_arg => ukmBytesNew(Output) ~> return_value_to_arg
+ ...
+
+
+ Output:Bytes
+
+
+ rule
+
+ push_status => .K
+ ...
+
+
+ Status:Int
+
+
+ .List => ListItem(Status)
+ ...
+
+
+ rule
+ check_eq I:Int => .K ...
+ ListItem(I) => .List ...
endmodule
```