From 90a59618a49fd33724742c3f795581831033eb29 Mon Sep 17 00:00:00 2001 From: "g. nicholas d'andrea" Date: Sun, 16 Jun 2024 17:28:34 -0400 Subject: [PATCH] Add scope collection to pointer schema --- .../web/spec/pointer/collection/scope.mdx | 11 ++ packages/web/src/schemas.ts | 2 +- schemas/pointer.schema.yaml | 130 ++++++++++++------ schemas/pointer/collection.schema.yaml | 8 ++ schemas/pointer/collection/scope.schema.yaml | 42 ++++++ schemas/pointer/expression.schema.yaml | 3 + 6 files changed, 150 insertions(+), 46 deletions(-) create mode 100644 packages/web/spec/pointer/collection/scope.mdx create mode 100644 schemas/pointer/collection/scope.schema.yaml diff --git a/packages/web/spec/pointer/collection/scope.mdx b/packages/web/spec/pointer/collection/scope.mdx new file mode 100644 index 00000000..2a8c92c8 --- /dev/null +++ b/packages/web/spec/pointer/collection/scope.mdx @@ -0,0 +1,11 @@ +--- +sidebar_position: 5 +--- + +import SchemaViewer from "@site/src/components/SchemaViewer"; + +# Scope + + diff --git a/packages/web/src/schemas.ts b/packages/web/src/schemas.ts index 4beee819..38f6c9f0 100644 --- a/packages/web/src/schemas.ts +++ b/packages/web/src/schemas.ts @@ -103,7 +103,7 @@ export const schemaIndex: SchemaIndex = { ...( [ - "group", "list", "conditional" + "group", "list", "conditional", "scope" ].map(collection => ({ [`schema:ethdebug/format/pointer/collection/${collection}`]: { href: `/spec/pointer/collection/${collection}` diff --git a/schemas/pointer.schema.yaml b/schemas/pointer.schema.yaml index 100bc11e..c2ce8dc7 100644 --- a/schemas/pointer.schema.yaml +++ b/schemas/pointer.schema.yaml @@ -142,53 +142,93 @@ examples: length: $wordsize - # example `string storage` allocation - group: - # for short strings, the length is stored as 2n in the last byte of slot - - name: "length-flag" - location: storage - slot: 0 - offset: - $difference: - - $wordsize - - 1 - length: 1 - - # long strings may use full word to describe length as 2n+1 - - name: "long-length-data" - location: storage - slot: - .slot: "length-flag" - offset: 0 - length: $wordsize + define: + "contract-variable-slot": 0 + in: + group: + # for short strings, the length is stored as 2n in the last byte of slot + - name: "length-flag" + location: storage + slot: contract-variable-slot + offset: + $difference: [$wordsize, 1] + length: 1 - # define the region representing the string data itself conditionally - # based on odd or even length data - - if: - $remainder: - - $read: "length-flag" - - 2 - then: - name: "string" + # long strings may use full word to describe length as 2n+1 + - name: "long-string-length-data" location: storage - slot: - $keccak256: - - .slot: "length-flag" + slot: contract-variable-slot offset: 0 - length: - # length n is encoded as 2n+1 - $quotient: - - $difference: - - $read: "long-length-data" + length: $wordsize + + # define the region representing the string data itself conditionally + # based on odd or even length data + - if: + $remainder: + - $sum: + - $read: "length-flag" - 1 - 2 - else: - name: "string" - location: storage - slot: - .slot: "length-flag" - offset: 0 - length: - # length n is encoded as 2n - $quotient: - - $read: "length-flag" - - 2 + + # short string case (flag is even) + then: + define: + "string-length": + $quotient: [{ $read: "length-flag" }, 2] + in: + name: "string" + location: storage + slot: "contract-variable-slot" + offset: 0 + length: "string-length" + + # long string case (flag is odd) + else: + define: + "string-length": + $quotient: + - $difference: + - $read: "long-string-length-data" + - 1 + - 2 + + "start-slot": + $keccak256: ["contract-variable-slot"] + + "total-slots": + # account for both zero and nonzero slot remainders by adding + # $wordsize-1 to the length before dividing + $quotient: + - $sum: ["string-length", { $difference: [$wordsize, 1] }] + - $wordsize + in: + list: + count: "total-slots" + each: "i" + is: + define: + "current-slot": + $sum: ["start-slot", "i"] + "previous-length": + $product: ["i", $wordsize] + in: + # conditional based on whether this is the last slot: + # is the string length longer than the previous length + # plus this whole slot? + if: + $difference: + - "string-length" + - $sum: ["previous-length", "$wordsize"] + then: + # include the whole slot + name: "string" + location: storage + slot: "current-slot" + else: + # include only what's left in the string + name: "string" + location: storage + slot: "current-slot" + offset: 0 + length: + $difference: ["string-length", "previous-length"] diff --git a/schemas/pointer/collection.schema.yaml b/schemas/pointer/collection.schema.yaml index f374d061..556e830c 100644 --- a/schemas/pointer/collection.schema.yaml +++ b/schemas/pointer/collection.schema.yaml @@ -14,6 +14,8 @@ allOf: - list - required: - if + - required: + - define - if: required: - group @@ -31,3 +33,9 @@ allOf: - if then: $ref: "schema:ethdebug/format/pointer/collection/conditional" + + - if: + required: + - define + then: + $ref: "schema:ethdebug/format/pointer/collection/scope" diff --git a/schemas/pointer/collection/scope.schema.yaml b/schemas/pointer/collection/scope.schema.yaml new file mode 100644 index 00000000..f1c4bc42 --- /dev/null +++ b/schemas/pointer/collection/scope.schema.yaml @@ -0,0 +1,42 @@ +$schema: "https://json-schema.org/draft/2020-12/schema" +$id: "schema:ethdebug/format/pointer/collection/scope" + +title: ethdebug/format/pointer/collection/scope +description: | + A pointer defined with the aid of additional variables with values specified + as expressions. + + Variables are specified by the `define` field as an object mapping of + expression by identifier. Variables are specified **in order**, so that + later appearing variables may reference earlier ones in the same object. + +type: object + +properties: + define: + title: Mapping of variables to expression value + type: object + patternProperties: + "^[a-zA-Z_\\-]+[a-zA-Z0-9$_\\-]*$": + $ref: "schema:ethdebug/format/pointer/expression" + additionalProperties: false + in: + $ref: "schema:ethdebug/format/pointer" + +required: + - define + - in + +additionalProperties: false + +examples: + - define: + example-offset: + $sum: [1, 2] + example-length: + $product: [2, $wordsize] + in: + name: example + location: memory + offset: example-offset + length: example-length diff --git a/schemas/pointer/expression.schema.yaml b/schemas/pointer/expression.schema.yaml index 55fbdbb3..6a7ce421 100644 --- a/schemas/pointer/expression.schema.yaml +++ b/schemas/pointer/expression.schema.yaml @@ -61,6 +61,9 @@ $defs: A tuple of two expressions where the second is to be subtracted from the first. + If the second operand is larger than the first, the result of this + arithmetic operation is defined to equal zero (`0`). + (i.e., `{ "$difference": [a, b] }` equals `a` minus `b`.) $ref: "#/$defs/Operands" minItems: 2