diff --git a/.gas-snapshot b/.gas-snapshot index c07727f..ad998fb 100644 --- a/.gas-snapshot +++ b/.gas-snapshot @@ -1,69 +1,60 @@ -LibBloomTest:testLibBloomNoFalseNegatives(bytes32[],uint256,uint256) (runs: 1970, μ: 40231, ~: 34931) -LibBloomTest:testLibBloomVaguelyAvoidsFalsePositives(uint256,uint8) (runs: 2048, μ: 1552760, ~: 23505) +LibBloomTest:testLibBloomNoFalseNegatives(bytes32[],uint256,uint256) (runs: 2048, μ: 38135, ~: 30080) +LibBloomTest:testLibBloomVaguelyAvoidsFalsePositives(uint256,uint8) (runs: 2048, μ: 1785796, ~: 13724) LibBytecodeCheckNoOOBPointersTest:testCheckNoOOBPointers0() (gas: 421) LibBytecodeCheckNoOOBPointersTest:testCheckNoOOBPointers1() (gas: 449) -LibBytecodeCheckNoOOBPointersTest:testCheckNoOOBPointers1Fail(bytes) (runs: 2022, μ: 5968, ~: 5949) -LibBytecodeCheckNoOOBPointersTest:testCheckNoOOBPointersConforming(bytes,uint256,bytes32) (runs: 2048, μ: 18014, ~: 15878) -LibBytecodeCheckNoOOBPointersTest:testCheckNoOOBPointersCorruptOffsetPointer(bytes,uint8,bytes32,uint8) (runs: 1349, μ: 23977, ~: 21571) -LibBytecodeCheckNoOOBPointersTest:testCheckNoOOBPointersCorruptOpsCount(bytes,uint8,bytes32,uint8) (runs: 1406, μ: 24561, ~: 22378) -LibBytecodeCheckNoOOBPointersTest:testCheckNoOOBPointersCorruptSourcesCount(bytes,uint8,bytes32,uint8) (runs: 1875, μ: 20024, ~: 18910) -LibBytecodeCheckNoOOBPointersTest:testCheckNoOOBPointersEndGarbage(bytes,bytes) (runs: 2023, μ: 17034, ~: 15942) -LibBytecodeCheckNoOOBPointersTest:testCheckNoOOBPointersHeaderTruncated(bytes,uint8,bytes32,uint256) (runs: 1472, μ: 25909, ~: 23510) -LibBytecodeCheckNoOOBPointersTest:testCheckNoOOBPointersInputsNotMonotonic(bytes,uint8,bytes32,uint256,uint256) (runs: 1482, μ: 28400, ~: 26010) -LibBytecodeCheckNoOOBPointersTest:testCheckNoOOBPointersOffsetsTruncated(bytes,uint8,uint256) (runs: 1755, μ: 10515, ~: 10554) -LibBytecodeCheckNoOOBPointersTest:testCheckNoOOBPointersOutputsNotMonotonic(bytes,uint8,bytes32,uint256,uint256) (runs: 1482, μ: 28390, ~: 26146) -LibBytecodeCheckNoOOBPointersTest:testCheckNoOOBPointersSourceTruncated(bytes,uint8,bytes32,uint8) (runs: 1406, μ: 24741, ~: 22550) -LibBytecodeCheckNoOOBPointersTest:testCheckNoOOBPointersTrailingOffsetBytes(bytes,bytes,uint8,bytes32) (runs: 1479, μ: 28945, ~: 25847) +LibBytecodeCheckNoOOBPointersTest:testCheckNoOOBPointers1Fail(bytes) (runs: 2048, μ: 5970, ~: 5949) +LibBytecodeCheckNoOOBPointersTest:testCheckNoOOBPointersConforming(bytes,uint256,bytes32) (runs: 2048, μ: 10604, ~: 8842) +LibBytecodeCheckNoOOBPointersTest:testCheckNoOOBPointersCorruptOffsetPointer(bytes,uint8,bytes32,uint8) (runs: 2048, μ: 16757, ~: 14890) +LibBytecodeCheckNoOOBPointersTest:testCheckNoOOBPointersCorruptOpsCount(bytes,uint8,bytes32,uint8) (runs: 2048, μ: 17474, ~: 15764) +LibBytecodeCheckNoOOBPointersTest:testCheckNoOOBPointersCorruptSourcesCount(bytes,uint8,bytes32,uint8) (runs: 2048, μ: 13079, ~: 12121) +LibBytecodeCheckNoOOBPointersTest:testCheckNoOOBPointersEndGarbage(bytes,bytes) (runs: 2048, μ: 12075, ~: 11058) +LibBytecodeCheckNoOOBPointersTest:testCheckNoOOBPointersHeaderTruncated(bytes,uint8,bytes32,uint256) (runs: 2048, μ: 18152, ~: 16236) +LibBytecodeCheckNoOOBPointersTest:testCheckNoOOBPointersInputsNotMonotonic(bytes,uint8,bytes32,uint256,uint256) (runs: 2048, μ: 19761, ~: 17786) +LibBytecodeCheckNoOOBPointersTest:testCheckNoOOBPointersOffsetsTruncated(bytes,uint8,uint256) (runs: 2048, μ: 7312, ~: 7454) +LibBytecodeCheckNoOOBPointersTest:testCheckNoOOBPointersOutputsNotMonotonic(bytes,uint8,bytes32,uint256,uint256) (runs: 2048, μ: 19751, ~: 17752) +LibBytecodeCheckNoOOBPointersTest:testCheckNoOOBPointersSourceTruncated(bytes,uint8,bytes32,uint8) (runs: 2048, μ: 17653, ~: 15934) +LibBytecodeCheckNoOOBPointersTest:testCheckNoOOBPointersTrailingOffsetBytes(bytes,bytes,uint8,bytes32) (runs: 2048, μ: 21400, ~: 18933) LibBytecodeSourceCountTest:testSourceCount0() (gas: 343) -LibBytecodeSourceCountTest:testSourceCount1(bytes) (runs: 2037, μ: 3611, ~: 3608) +LibBytecodeSourceCountTest:testSourceCount1(bytes) (runs: 2048, μ: 3612, ~: 3608) LibBytecodeSourceCountTest:testSourceCountReference(bytes) (runs: 2048, μ: 827, ~: 824) -LibBytecodeSourceInputsOutputsTest:testSourceInputsOutputsAgainstSlow(bytes,uint256,uint256,bytes32) (runs: 1661, μ: 26341, ~: 22906) -LibBytecodeSourceInputsOutputsTest:testSourceInputsOutputsIndexOutOfBounds(bytes,uint256,uint256,bytes32) (runs: 2048, μ: 23602, ~: 21047) +LibBytecodeSourceInputsOutputsTest:testSourceInputsOutputsAgainstSlow(bytes,uint256,uint256,bytes32) (runs: 2048, μ: 16973, ~: 14633) +LibBytecodeSourceInputsOutputsTest:testSourceInputsOutputsIndexOutOfBounds(bytes,uint256,uint256,bytes32) (runs: 2048, μ: 14549, ~: 12958) LibBytecodeSourceOpsCountTest:testSourceOpsCount() (gas: 2163) -LibBytecodeSourceOpsCountTest:testSourceOpsCountAgainstSlow(bytes,uint256,uint256,bytes32) (runs: 1659, μ: 26295, ~: 22735) -LibBytecodeSourceOpsCountTest:testSourceOpsCountIndexOutOfBounds(bytes,uint256,uint256,bytes32) (runs: 2048, μ: 23606, ~: 21108) -LibBytecodeSourcePointerTest:testSourcePointerAgainstSlow(bytes,uint256,uint256,bytes32) (runs: 1640, μ: 26289, ~: 22593) +LibBytecodeSourceOpsCountTest:testSourceOpsCountAgainstSlow(bytes,uint256,uint256,bytes32) (runs: 2048, μ: 16795, ~: 14466) +LibBytecodeSourceOpsCountTest:testSourceOpsCountIndexOutOfBounds(bytes,uint256,uint256,bytes32) (runs: 2048, μ: 14448, ~: 12984) +LibBytecodeSourcePointerTest:testSourcePointerAgainstSlow(bytes,uint256,uint256,bytes32) (runs: 2048, μ: 16649, ~: 14320) LibBytecodeSourcePointerTest:testSourcePointerEmpty0(uint256) (runs: 2048, μ: 5407, ~: 5407) LibBytecodeSourcePointerTest:testSourcePointerEmpty1(uint256) (runs: 2048, μ: 5486, ~: 5486) -LibBytecodeSourcePointerTest:testSourcePointerIndexOutOfBounds(bytes,uint256,uint256,bytes32) (runs: 2048, μ: 23572, ~: 21102) +LibBytecodeSourcePointerTest:testSourcePointerIndexOutOfBounds(bytes,uint256,uint256,bytes32) (runs: 2048, μ: 14494, ~: 13076) LibBytecodeSourceRelativeOffsetTest:testSourceRelativeOffsetHappy() (gas: 1215) LibBytecodeSourceRelativeOffsetTest:testSourceRelativeOffsetIndexError() (gas: 85666) -LibBytecodeSourceRelativeOffsetTest:testSourceRelativeOffsetReference(bytes,uint256,uint256,bytes32) (runs: 1652, μ: 25544, ~: 22042) -LibBytecodeSourceStackAllocationTest:testSourceStackAllocationAgainstSlow(bytes,uint256,uint256,bytes32) (runs: 1630, μ: 26518, ~: 23055) -LibBytecodeSourceStackAllocationTest:testSourceStackAllocationIndexOutOfBounds(bytes,uint256,uint256,bytes32) (runs: 2048, μ: 23528, ~: 21105) +LibBytecodeSourceRelativeOffsetTest:testSourceRelativeOffsetReference(bytes,uint256,uint256,bytes32) (runs: 2048, μ: 16124, ~: 13660) +LibBytecodeSourceStackAllocationTest:testSourceStackAllocationAgainstSlow(bytes,uint256,uint256,bytes32) (runs: 2048, μ: 16835, ~: 14408) +LibBytecodeSourceStackAllocationTest:testSourceStackAllocationIndexOutOfBounds(bytes,uint256,uint256,bytes32) (runs: 2048, μ: 14456, ~: 12875) LibContextHashTest:testFuzzHash0() (gas: 3537) LibContextHashTest:testHash(uint256) (runs: 2048, μ: 279, ~: 279) LibContextHashTest:testHashGas0() (gas: 206) -LibContextHashTest:testSignedContextArrayHashReferenceImplementation((address,bytes32[],bytes)[]) (runs: 100, μ: 2614880, ~: 2346946) +LibContextHashTest:testSignedContextArrayHashReferenceImplementation((address,bytes32[],bytes)[]) (runs: 100, μ: 2424301, ~: 1983631) LibContextHashTest:testSignedContextArrayHashReferenceImplementation0() (gas: 2172) LibContextHashTest:testSignedContextHashEncodeGas0() (gas: 1441) LibContextHashTest:testSignedContextHashGas0() (gas: 824) -LibContextHashTest:testSignedContextHashReferenceImplementation((address,bytes32[],bytes)) (runs: 100, μ: 13598, ~: 13190) +LibContextHashTest:testSignedContextHashReferenceImplementation((address,bytes32[],bytes)) (runs: 100, μ: 13641, ~: 13569) LibContextTest:testBase() (gas: 611) LibContextTest:testBuild0() (gas: 5010) LibContextTest:testBuildGas0() (gas: 953) LibContextTest:testBuildStructureReferenceImplementation(bytes32[][]) (runs: 100, μ: 4645490, ~: 4797429) -LibDeployerDiscoverableTest:testTouchDeployerV4Mock() (gas: 175612) -LibEncodedDispatchTest:testRoundTrip(address,uint256,uint16) (runs: 2048, μ: 4406, ~: 4681) -LibEvaluableTest:testEvaluableV2HashDifferent((address,address,address),(address,address,address)) (runs: 2048, μ: 4233, ~: 4233) -LibEvaluableTest:testEvaluableV2HashGas0() (gas: 295) -LibEvaluableTest:testEvaluableV2HashGasSlow0() (gas: 580) -LibEvaluableTest:testEvaluableV2HashSame((address,address,address)) (runs: 2048, μ: 1003, ~: 1003) -LibEvaluableTest:testEvaluableV2HashSensitivity((address,address,address),(address,address,address)) (runs: 2045, μ: 5990, ~: 5990) -LibEvaluableTest:testEvaluableV2KnownHash() (gas: 353) -LibEvaluableTest:testEvaluableV2ReferenceImplementation((address,address,address)) (runs: 2048, μ: 1066, ~: 1066) -LibEvaluableTest:testEvaluableV3BytecodeLengthSensitivity() (gas: 898) -LibEvaluableTest:testEvaluableV3HashDifferent((address,address,bytes),(address,address,bytes)) (runs: 2048, μ: 5185, ~: 5183) -LibEvaluableTest:testEvaluableV3HashGas0() (gas: 429) -LibEvaluableTest:testEvaluableV3HashGasSlow0() (gas: 758) -LibEvaluableTest:testEvaluableV3HashSame((address,address,bytes)) (runs: 2048, μ: 1599, ~: 1588) -LibEvaluableTest:testEvaluableV3HashSensitivity((address,address,bytes),(address,address,bytes)) (runs: 2044, μ: 8320, ~: 8293) -LibEvaluableTest:testEvaluableV3KnownHash() (gas: 602) -LibEvaluableTest:testEvaluableV3ReferenceImplementation((address,address,bytes)) (runs: 2048, μ: 1704, ~: 1693) -LibGenParseMetaBuildMetaTest:testBuildMeta((bytes32,string)[]) (runs: 745, μ: 3674384, ~: 2813977) -LibGenParseMetaBuildMetaTest:testRoundMetaExpanderDeeper((bytes32,string)[],uint8,bytes32) (runs: 366, μ: 6652382, ~: 6359523) -LibGenParseMetaBuildMetaTest:testRoundMetaExpanderShallow((bytes32,string)[],uint8,bytes32) (runs: 715, μ: 3521627, ~: 3137421) -LibGenParseMetaFindExpanderTest:testFindExpanderSmall((bytes32,string)[]) (runs: 254, μ: 41946, ~: 33181) +LibEvaluableTest:testEvaluableV4BytecodeLengthSensitivity() (gas: 897) +LibEvaluableTest:testEvaluableV4HashDifferent((address,address,bytes),(address,address,bytes)) (runs: 2048, μ: 5148, ~: 5149) +LibEvaluableTest:testEvaluableV4HashGas0() (gas: 429) +LibEvaluableTest:testEvaluableV4HashGasSlow0() (gas: 768) +LibEvaluableTest:testEvaluableV4HashSame((address,address,bytes)) (runs: 2048, μ: 1565, ~: 1554) +LibEvaluableTest:testEvaluableV4HashSensitivity((address,address,bytes),(address,address,bytes)) (runs: 2048, μ: 8278, ~: 8263) +LibEvaluableTest:testEvaluableV4KnownHash() (gas: 580) +LibEvaluableTest:testEvaluableV4ReferenceImplementation((address,address,bytes)) (runs: 2048, μ: 1693, ~: 1682) +LibGenParseMetaBuildMetaTest:testBuildMeta((bytes32,string)[]) (runs: 2048, μ: 3700890, ~: 3857085) +LibGenParseMetaBuildMetaTest:testRoundMetaExpanderDeeper((bytes32,string)[],uint8,bytes32) (runs: 2048, μ: 6807238, ~: 6710253) +LibGenParseMetaBuildMetaTest:testRoundMetaExpanderShallow((bytes32,string)[],uint8,bytes32) (runs: 2048, μ: 3776067, ~: 4027823) +LibGenParseMetaFindExpanderTest:testFindExpanderSmall((bytes32,string)[]) (runs: 2048, μ: 41282, ~: 31299) LibNamespaceTest:testQualifyNamespaceGas0(uint256,address) (runs: 2048, μ: 359, ~: 359) LibNamespaceTest:testQualifyNamespaceGasSlow0(uint256,address) (runs: 2048, μ: 566, ~: 566) LibNamespaceTest:testQualifyNamespaceReferenceImplementation(uint256,address) (runs: 2048, μ: 722, ~: 722) diff --git a/src/error/ErrBytecode.sol b/src/error/ErrBytecode.sol index 30313a5..08590de 100644 --- a/src/error/ErrBytecode.sol +++ b/src/error/ErrBytecode.sol @@ -2,9 +2,6 @@ // SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd pragma solidity ^0.8.25; -/// @dev Workaround for https://github.com/foundry-rs/foundry/issues/6572 -contract ErrBytecode {} - /// Thrown when a bytecode source index is out of bounds. /// @param sourceIndex The source index that was out of bounds. /// @param bytecode The bytecode that was inspected. diff --git a/src/error/ErrExtern.sol b/src/error/ErrExtern.sol index c5fdecf..017358f 100644 --- a/src/error/ErrExtern.sol +++ b/src/error/ErrExtern.sol @@ -2,9 +2,6 @@ // SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd pragma solidity ^0.8.25; -/// @dev Workaround for https://github.com/foundry-rs/foundry/issues/6572 -contract ErrExtern {} - /// Thrown when the extern interface is not supported. error NotAnExternContract(address extern); diff --git a/src/interface/unstable/IInterpreterCallerV4.sol b/src/interface/IInterpreterCallerV4.sol similarity index 95% rename from src/interface/unstable/IInterpreterCallerV4.sol rename to src/interface/IInterpreterCallerV4.sol index ddb5309..66c88f0 100644 --- a/src/interface/unstable/IInterpreterCallerV4.sol +++ b/src/interface/IInterpreterCallerV4.sol @@ -4,7 +4,7 @@ pragma solidity ^0.8.18; // Exported for convenience. //forge-lint: disable-next-line(unused-import) -import {IParserV2} from "../IParserV2.sol"; +import {IParserV2} from "./IParserV2.sol"; import {IInterpreterStoreV3} from "./IInterpreterStoreV3.sol"; import {IInterpreterV4} from "./IInterpreterV4.sol"; import { @@ -15,7 +15,7 @@ import { SIGNED_CONTEXT_SIGNER_OFFSET, SIGNED_CONTEXT_CONTEXT_OFFSET, SIGNED_CONTEXT_SIGNATURE_OFFSET -} from "../IInterpreterCallerV3.sol"; +} from "./deprecated/v2/IInterpreterCallerV3.sol"; //forge-lint: disable-end diff --git a/src/interface/unstable/IInterpreterExternV4.sol b/src/interface/IInterpreterExternV4.sol similarity index 100% rename from src/interface/unstable/IInterpreterExternV4.sol rename to src/interface/IInterpreterExternV4.sol diff --git a/src/interface/unstable/IInterpreterStoreV3.sol b/src/interface/IInterpreterStoreV3.sol similarity index 98% rename from src/interface/unstable/IInterpreterStoreV3.sol rename to src/interface/IInterpreterStoreV3.sol index 1ef7e28..fc56868 100644 --- a/src/interface/unstable/IInterpreterStoreV3.sol +++ b/src/interface/IInterpreterStoreV3.sol @@ -4,7 +4,7 @@ pragma solidity ^0.8.18; // Exported for convenience. //forge-lint: disable-next-line(unused-import) -import {StateNamespace, FullyQualifiedNamespace, NO_STORE} from "../IInterpreterStoreV2.sol"; +import {StateNamespace, FullyQualifiedNamespace, NO_STORE} from "./deprecated/v2/IInterpreterStoreV2.sol"; /// @title IInterpreterStoreV3 /// @notice Tracks state changes on behalf of an interpreter. A single store can diff --git a/src/interface/unstable/IInterpreterV4.sol b/src/interface/IInterpreterV4.sol similarity index 98% rename from src/interface/unstable/IInterpreterV4.sol rename to src/interface/IInterpreterV4.sol index b1279f6..5571bb1 100644 --- a/src/interface/unstable/IInterpreterV4.sol +++ b/src/interface/IInterpreterV4.sol @@ -33,7 +33,7 @@ import { // Exported for convenience. //forge-lint: disable-next-line(unused-import) OPCODE_STACK -} from "../IInterpreterV3.sol"; +} from "./deprecated/v2/IInterpreterV3.sol"; import {IInterpreterStoreV3} from "./IInterpreterStoreV3.sol"; type OperandV2 is bytes32; diff --git a/src/interface/IParserV2.sol b/src/interface/IParserV2.sol index 155c383..08b1b5b 100644 --- a/src/interface/IParserV2.sol +++ b/src/interface/IParserV2.sol @@ -4,7 +4,7 @@ pragma solidity ^0.8.18; // Reexport AuthoringMetaV2 for downstream use. //forge-lint: disable-next-line(unused-import) -import {AuthoringMetaV2} from "./deprecated/IParserV1.sol"; +import {AuthoringMetaV2} from "./deprecated/v1/IParserV1.sol"; interface IParserV2 { function parse2(bytes calldata data) external view returns (bytes calldata bytecode); diff --git a/src/interface/unstable/ISubParserV4.sol b/src/interface/ISubParserV4.sol similarity index 98% rename from src/interface/unstable/ISubParserV4.sol rename to src/interface/ISubParserV4.sol index 3c7b78f..cea444c 100644 --- a/src/interface/unstable/ISubParserV4.sol +++ b/src/interface/ISubParserV4.sol @@ -4,7 +4,7 @@ pragma solidity ^0.8.18; // Reexports for implementations to use. //forge-lint: disable-next-line(unused-import) -import {AuthoringMetaV2} from "../ISubParserV3.sol"; +import {AuthoringMetaV2} from "./deprecated/v2/ISubParserV3.sol"; //forge-lint: disable-next-line(unused-import) import {OperandV2} from "./IInterpreterV4.sol"; diff --git a/src/interface/deprecated/IDebugExpressionDeployerV1.sol b/src/interface/deprecated/v1/IDebugExpressionDeployerV1.sol similarity index 100% rename from src/interface/deprecated/IDebugExpressionDeployerV1.sol rename to src/interface/deprecated/v1/IDebugExpressionDeployerV1.sol diff --git a/src/interface/deprecated/IDebugExpressionDeployerV2.sol b/src/interface/deprecated/v1/IDebugExpressionDeployerV2.sol similarity index 100% rename from src/interface/deprecated/IDebugExpressionDeployerV2.sol rename to src/interface/deprecated/v1/IDebugExpressionDeployerV2.sol diff --git a/src/interface/deprecated/IDebugInterpreterV1.sol b/src/interface/deprecated/v1/IDebugInterpreterV1.sol similarity index 100% rename from src/interface/deprecated/IDebugInterpreterV1.sol rename to src/interface/deprecated/v1/IDebugInterpreterV1.sol diff --git a/src/interface/deprecated/IDebugInterpreterV2.sol b/src/interface/deprecated/v1/IDebugInterpreterV2.sol similarity index 100% rename from src/interface/deprecated/IDebugInterpreterV2.sol rename to src/interface/deprecated/v1/IDebugInterpreterV2.sol diff --git a/src/interface/deprecated/IExpressionDeployerV1.sol b/src/interface/deprecated/v1/IExpressionDeployerV1.sol similarity index 100% rename from src/interface/deprecated/IExpressionDeployerV1.sol rename to src/interface/deprecated/v1/IExpressionDeployerV1.sol diff --git a/src/interface/deprecated/IExpressionDeployerV2.sol b/src/interface/deprecated/v1/IExpressionDeployerV2.sol similarity index 100% rename from src/interface/deprecated/IExpressionDeployerV2.sol rename to src/interface/deprecated/v1/IExpressionDeployerV2.sol diff --git a/src/interface/deprecated/IExpressionDeployerV3.sol b/src/interface/deprecated/v1/IExpressionDeployerV3.sol similarity index 99% rename from src/interface/deprecated/IExpressionDeployerV3.sol rename to src/interface/deprecated/v1/IExpressionDeployerV3.sol index b43d921..bb6f06a 100644 --- a/src/interface/deprecated/IExpressionDeployerV3.sol +++ b/src/interface/deprecated/v1/IExpressionDeployerV3.sol @@ -2,7 +2,7 @@ // SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd pragma solidity ^0.8.18; -import {IInterpreterStoreV2} from "../IInterpreterStoreV2.sol"; +import {IInterpreterStoreV2} from "../v2/IInterpreterStoreV2.sol"; import {IInterpreterV2} from "./IInterpreterV2.sol"; string constant IERC1820_NAME_IEXPRESSION_DEPLOYER_V3 = "IExpressionDeployerV3"; diff --git a/src/interface/deprecated/IExpressionDeployerV4.sol b/src/interface/deprecated/v1/IExpressionDeployerV4.sol similarity index 99% rename from src/interface/deprecated/IExpressionDeployerV4.sol rename to src/interface/deprecated/v1/IExpressionDeployerV4.sol index bfecc78..bf2c864 100644 --- a/src/interface/deprecated/IExpressionDeployerV4.sol +++ b/src/interface/deprecated/v1/IExpressionDeployerV4.sol @@ -2,7 +2,7 @@ // SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd pragma solidity ^0.8.18; -import {IInterpreterStoreV2} from "../IInterpreterStoreV2.sol"; +import {IInterpreterStoreV2} from "../v2/IInterpreterStoreV2.sol"; import {IInterpreterV2} from "./IInterpreterV2.sol"; string constant IERC1820_NAME_IEXPRESSION_DEPLOYER_V4 = "IExpressionDeployerV4"; diff --git a/src/interface/deprecated/IInterpreterCallerV1.sol b/src/interface/deprecated/v1/IInterpreterCallerV1.sol similarity index 100% rename from src/interface/deprecated/IInterpreterCallerV1.sol rename to src/interface/deprecated/v1/IInterpreterCallerV1.sol diff --git a/src/interface/deprecated/IInterpreterCallerV2.sol b/src/interface/deprecated/v1/IInterpreterCallerV2.sol similarity index 98% rename from src/interface/deprecated/IInterpreterCallerV2.sol rename to src/interface/deprecated/v1/IInterpreterCallerV2.sol index 3e1b0bc..50fae36 100644 --- a/src/interface/deprecated/IInterpreterCallerV2.sol +++ b/src/interface/deprecated/v1/IInterpreterCallerV2.sol @@ -3,7 +3,7 @@ pragma solidity ^0.8.18; import {IExpressionDeployerV3} from "./IExpressionDeployerV3.sol"; -import {IInterpreterStoreV2} from "../IInterpreterStoreV2.sol"; +import {IInterpreterStoreV2} from "../v2/IInterpreterStoreV2.sol"; import {IInterpreterV2} from "./IInterpreterV2.sol"; /// Standard struct that can be embedded in ABIs in a consistent format for diff --git a/src/interface/deprecated/IInterpreterExternV1.sol b/src/interface/deprecated/v1/IInterpreterExternV1.sol similarity index 100% rename from src/interface/deprecated/IInterpreterExternV1.sol rename to src/interface/deprecated/v1/IInterpreterExternV1.sol diff --git a/src/interface/deprecated/IInterpreterExternV2.sol b/src/interface/deprecated/v1/IInterpreterExternV2.sol similarity index 100% rename from src/interface/deprecated/IInterpreterExternV2.sol rename to src/interface/deprecated/v1/IInterpreterExternV2.sol diff --git a/src/interface/deprecated/IInterpreterStoreV1.sol b/src/interface/deprecated/v1/IInterpreterStoreV1.sol similarity index 100% rename from src/interface/deprecated/IInterpreterStoreV1.sol rename to src/interface/deprecated/v1/IInterpreterStoreV1.sol diff --git a/src/interface/deprecated/IInterpreterV1.sol b/src/interface/deprecated/v1/IInterpreterV1.sol similarity index 100% rename from src/interface/deprecated/IInterpreterV1.sol rename to src/interface/deprecated/v1/IInterpreterV1.sol diff --git a/src/interface/deprecated/IInterpreterV2.sol b/src/interface/deprecated/v1/IInterpreterV2.sol similarity index 99% rename from src/interface/deprecated/IInterpreterV2.sol rename to src/interface/deprecated/v1/IInterpreterV2.sol index d874e7c..d0c1992 100644 --- a/src/interface/deprecated/IInterpreterV2.sol +++ b/src/interface/deprecated/v1/IInterpreterV2.sol @@ -5,7 +5,7 @@ pragma solidity ^0.8.18; // Exported for convenience. //forge-lint: disable-next-line(unused-import) import {EncodedDispatch, StateNamespace, Operand, DEFAULT_STATE_NAMESPACE} from "./IInterpreterV1.sol"; -import {FullyQualifiedNamespace, IInterpreterStoreV2} from "../IInterpreterStoreV2.sol"; +import {FullyQualifiedNamespace, IInterpreterStoreV2} from "../v2/IInterpreterStoreV2.sol"; /// @dev For maximum compatibility with external contracts, the `IInterpreterV2` /// should implement an opcode that reads from the stack by index as opcode `0`. diff --git a/src/interface/deprecated/IParserV1.sol b/src/interface/deprecated/v1/IParserV1.sol similarity index 100% rename from src/interface/deprecated/IParserV1.sol rename to src/interface/deprecated/v1/IParserV1.sol diff --git a/src/interface/deprecated/IParserV1View.sol b/src/interface/deprecated/v1/IParserV1View.sol similarity index 100% rename from src/interface/deprecated/IParserV1View.sol rename to src/interface/deprecated/v1/IParserV1View.sol diff --git a/src/interface/deprecated/ISubParserV1.sol b/src/interface/deprecated/v1/ISubParserV1.sol similarity index 100% rename from src/interface/deprecated/ISubParserV1.sol rename to src/interface/deprecated/v1/ISubParserV1.sol diff --git a/src/interface/deprecated/ISubParserV2.sol b/src/interface/deprecated/v1/ISubParserV2.sol similarity index 100% rename from src/interface/deprecated/ISubParserV2.sol rename to src/interface/deprecated/v1/ISubParserV2.sol diff --git a/src/interface/IInterpreterCallerV3.sol b/src/interface/deprecated/v2/IInterpreterCallerV3.sol similarity index 95% rename from src/interface/IInterpreterCallerV3.sol rename to src/interface/deprecated/v2/IInterpreterCallerV3.sol index 7acf436..8d3c98f 100644 --- a/src/interface/IInterpreterCallerV3.sol +++ b/src/interface/deprecated/v2/IInterpreterCallerV3.sol @@ -4,7 +4,7 @@ pragma solidity ^0.8.18; // Exported for convenience. //forge-lint: disable-next-line(unused-import) -import {IParserV2} from "./IParserV2.sol"; +import {IParserV2} from "../../IParserV2.sol"; import {IInterpreterStoreV2} from "./IInterpreterStoreV2.sol"; import {IInterpreterV3} from "./IInterpreterV3.sol"; import { @@ -15,7 +15,7 @@ import { SIGNED_CONTEXT_SIGNER_OFFSET, SIGNED_CONTEXT_CONTEXT_OFFSET, SIGNED_CONTEXT_SIGNATURE_OFFSET -} from "./deprecated/IInterpreterCallerV2.sol"; +} from "../v1/IInterpreterCallerV2.sol"; //forge-lint: disable-end diff --git a/src/interface/IInterpreterExternV3.sol b/src/interface/deprecated/v2/IInterpreterExternV3.sol similarity index 95% rename from src/interface/IInterpreterExternV3.sol rename to src/interface/deprecated/v2/IInterpreterExternV3.sol index 3680441..0c4cb48 100644 --- a/src/interface/IInterpreterExternV3.sol +++ b/src/interface/deprecated/v2/IInterpreterExternV3.sol @@ -4,7 +4,7 @@ pragma solidity ^0.8.18; // Exported for convenience. //forge-lint: disable-next-line(unused-import) -import {EncodedExternDispatch, ExternDispatch} from "./deprecated/IInterpreterExternV2.sol"; +import {EncodedExternDispatch, ExternDispatch} from "../v1/IInterpreterExternV2.sol"; /// @title IInterpreterExternV3 /// Handle a single dispatch from some calling contract with an array of diff --git a/src/interface/IInterpreterStoreV2.sol b/src/interface/deprecated/v2/IInterpreterStoreV2.sol similarity index 98% rename from src/interface/IInterpreterStoreV2.sol rename to src/interface/deprecated/v2/IInterpreterStoreV2.sol index 7f0db31..2798c1f 100644 --- a/src/interface/IInterpreterStoreV2.sol +++ b/src/interface/deprecated/v2/IInterpreterStoreV2.sol @@ -4,7 +4,7 @@ pragma solidity ^0.8.18; // Exported for convenience. //forge-lint: disable-next-line(unused-import) -import {StateNamespace, FullyQualifiedNamespace, NO_STORE} from "./deprecated/IInterpreterStoreV1.sol"; +import {StateNamespace, FullyQualifiedNamespace, NO_STORE} from "../v1/IInterpreterStoreV1.sol"; /// @title IInterpreterStoreV2 /// @notice Tracks state changes on behalf of an interpreter. A single store can diff --git a/src/interface/IInterpreterV3.sol b/src/interface/deprecated/v2/IInterpreterV3.sol similarity index 97% rename from src/interface/IInterpreterV3.sol rename to src/interface/deprecated/v2/IInterpreterV3.sol index 580c597..4308e93 100644 --- a/src/interface/IInterpreterV3.sol +++ b/src/interface/deprecated/v2/IInterpreterV3.sol @@ -38,7 +38,7 @@ import { // Exported for convenience. //forge-lint: disable-next-line(unused-import) OPCODE_STACK -} from "./deprecated/IInterpreterV2.sol"; +} from "../v1/IInterpreterV2.sol"; interface IInterpreterV3 { function functionPointers() external view returns (bytes calldata); diff --git a/src/interface/IParserPragmaV1.sol b/src/interface/deprecated/v2/IParserPragmaV1.sol similarity index 100% rename from src/interface/IParserPragmaV1.sol rename to src/interface/deprecated/v2/IParserPragmaV1.sol diff --git a/src/interface/ISubParserV3.sol b/src/interface/deprecated/v2/ISubParserV3.sol similarity index 97% rename from src/interface/ISubParserV3.sol rename to src/interface/deprecated/v2/ISubParserV3.sol index 5d769bc..7a65fae 100644 --- a/src/interface/ISubParserV3.sol +++ b/src/interface/deprecated/v2/ISubParserV3.sol @@ -4,13 +4,13 @@ pragma solidity ^0.8.18; // Reexports for implementations to use. //forge-lint: disable-next-line(unused-import) -import {AuthoringMetaV2} from "./deprecated/IParserV1.sol"; +import {AuthoringMetaV2} from "../v1/IParserV1.sol"; // Exported for convenience. //forge-lint: disable-next-line(unused-import) -import {Operand} from "./deprecated/IInterpreterV2.sol"; +import {Operand} from "../v1/IInterpreterV2.sol"; // Exported for convenience. //forge-lint: disable-next-line(unused-import) -import {COMPATIBILITY_V2, COMPATIBILITY_V3, COMPATIBILITY_V4} from "./deprecated/ISubParserV2.sol"; +import {COMPATIBILITY_V2, COMPATIBILITY_V3, COMPATIBILITY_V4} from "../v1/ISubParserV2.sol"; /// @dev A compatibility version for the subparser interface. /// diff --git a/src/lib/caller/LibContext.sol b/src/lib/caller/LibContext.sol index d28b3bf..5e1fc69 100644 --- a/src/lib/caller/LibContext.sol +++ b/src/lib/caller/LibContext.sol @@ -13,15 +13,24 @@ import { SIGNED_CONTEXT_SIGNER_OFFSET, SIGNED_CONTEXT_SIGNATURE_OFFSET, SIGNED_CONTEXT_CONTEXT_OFFSET -} from "../../interface/IInterpreterCallerV3.sol"; +} from "../../interface/IInterpreterCallerV4.sol"; /// Thrown when the ith signature from a list of signed contexts is invalid. +/// @param i The index of the invalid signature in the list of signed contexts. error InvalidSignature(uint256 i); +/// @dev CONTEXT_BASE_COLUMN and CONTEXT_BASE_ROWS are the dimensions of the base +/// context provided by `LibContext.base()`. These constants are not required to +/// use the base context but are provided for convenience when working with it. uint256 constant CONTEXT_BASE_COLUMN = 0; +/// @dev CONTEXT_BASE_ROWS is the number of rows in the base context, which is +/// always 2 for the `msg.sender` and address of the calling contract. uint256 constant CONTEXT_BASE_ROWS = 2; +/// @dev The row index of the `msg.sender` in the base context. uint256 constant CONTEXT_BASE_ROW_SENDER = 0; +/// @dev The row index of the address of the calling contract in the base +/// context. uint256 constant CONTEXT_BASE_ROW_CALLING_CONTRACT = 1; /// @title LibContext diff --git a/src/lib/caller/LibEvaluable.sol b/src/lib/caller/LibEvaluable.sol index 3624aca..810061a 100644 --- a/src/lib/caller/LibEvaluable.sol +++ b/src/lib/caller/LibEvaluable.sol @@ -5,40 +5,22 @@ pragma solidity ^0.8.25; /// Export dispair interfaces for convenience downstream. // Exported for convenience. //forge-lint: disable-next-line(unused-import) -import {IInterpreterStoreV2} from "../../interface/IInterpreterStoreV2.sol"; -// Exported for convenience. -//forge-lint: disable-next-line(unused-import) -import {IInterpreterV2} from "../../interface/deprecated/IInterpreterV2.sol"; -import {EvaluableV2} from "../../interface/deprecated/IInterpreterCallerV2.sol"; +import {IInterpreterStoreV3} from "../../interface/IInterpreterStoreV3.sol"; -import {EvaluableV3} from "../../interface/IInterpreterCallerV3.sol"; +import {EvaluableV4} from "../../interface/IInterpreterCallerV4.sol"; /// @title LibEvaluable /// @notice Common logic to provide consistent implementations of common tasks /// that could be arbitrarily/ambiguously implemented, but work much better if /// consistently implemented. library LibEvaluable { - /// Hashes an `EvaluableV2`, ostensibly so that only the hash need be stored, - /// thus only storing a single `uint256` instead of 3x `uint160`. - /// @param evaluable The evaluable to hash. - /// @return evaluableHash Standard hash of the evaluable. - function hash(EvaluableV2 memory evaluable) internal pure returns (bytes32 evaluableHash) { - // `Evaluable` does NOT contain any dynamic types so it is safe to encode - // packed for hashing, and is preferable due to the smaller/simpler - // in-memory structure. It also makes it easier to replicate the logic - // offchain as a simple concatenation of bytes. - assembly ("memory-safe") { - evaluableHash := keccak256(evaluable, 0x60) - } - } - - /// Hashes an `EvaluableV3`, ostensibly so that only the hash need be stored, + /// Hashes an `EvaluableV4`, ostensibly so that only the hash need be stored, /// thus only storing a single `bytes32` instead of 2x `address` and an /// arbitrary length `bytes`. /// https://github.com/rainlanguage/rain.lib.hash?tab=readme-ov-file#the-pattern /// @param evaluable The evaluable to hash. /// @return evaluableHash Standard hash of the evaluable. - function hash(EvaluableV3 memory evaluable) internal pure returns (bytes32) { + function hash(EvaluableV4 memory evaluable) internal pure returns (bytes32) { bytes memory bytecode = evaluable.bytecode; bytes32 evaluableHash; assembly ("memory-safe") { diff --git a/src/lib/codegen/LibGenParseMeta.sol b/src/lib/codegen/LibGenParseMeta.sol index 0daa2f4..c75fefb 100644 --- a/src/lib/codegen/LibGenParseMeta.sol +++ b/src/lib/codegen/LibGenParseMeta.sol @@ -20,7 +20,32 @@ uint256 constant META_ITEM_MASK = (1 << META_ITEM_SIZE) - 1; /// @dev For metadata builder. error DuplicateFingerprint(); +/// @title LibGenParseMeta +/// @notice Library for building parse meta from authoring meta, and generating +/// constant strings for the parse meta to be used in generated code. The parse +/// meta is a bytes array that is used to lookup word definitions. The parse meta +/// is built from the authoring meta, which is an array of `AuthoringMetaV2` that +/// contains the word and its corresponding opcode index. The parse meta is +/// structured in a way that allows for efficient lookups of word definitions +/// using bloom filters and fingerprints. The library provides functions to find +/// the best expander for a given set of authoring meta, build the parse meta +/// from the authoring meta and build depth, and generate a constant string for +/// the parse meta with a comment describing its structure. The main purpose of +/// this library is to optimize the size of the parse meta while maintaining +/// efficient lookups, which is important for the performance of the interpreter. library LibGenParseMeta { + /// @dev Finds the best expander for a given set of authoring meta. The best + /// expander is the one that produces the densest bloom filter at each depth, + /// which minimizes the number of items that need to be checked for each + /// lookup. The function returns the best seed, the corresponding expansion, + /// and the remaining authoring meta that could not be expanded with this + /// seed. The remaining authoring meta can then be used to find the next best + /// expander until all authoring meta has been expanded. + /// @param metas The authoring meta to find the best expander for. + /// @return bestSeed The best seed for the given authoring meta. + /// @return bestExpansion The corresponding expansion for the best seed. + /// @return remaining The remaining authoring meta that could not be expanded + /// with the best seed. function findBestExpander(AuthoringMetaV2[] memory metas) internal pure @@ -72,6 +97,32 @@ library LibGenParseMeta { } } + /// @dev Builds the parse meta from the authoring meta and build depth. The + /// parse meta is a bytes array with the following structure: + /// - 1 byte: The depth of the bloom filters + /// - 1 byte: The hashing seed + /// - The bloom filters, each is 32 bytes long, one for each build depth + /// - All the items for each word, each is 4 bytes long. Each item's first + /// byte is its opcode index, the remaining 3 bytes are the word + /// fingerprint. + /// The parse meta is used to lookup word definitions. To do a lookup, the + /// word is hashed with the seed, then the first byte of the hash is compared + /// against the bloom filter. If there is a hit then we count the number of + /// 1 bits in the bloom filter up to this item's 1 bit. We then treat this + /// as the index of the item in the items array. We then compare the word + /// fingerprint against the fingerprint of the item at this index. If the + /// fingerprints equal then we have a match, else we increment the seed and + /// try again with the next bloom filter, offsetting all the indexes by the + /// total bit count of the previous bloom filter. If we reach the end of the + /// bloom filters then we have a miss. + /// @param authoringMeta The authoring meta to build the parse meta from. + /// @param maxDepth The maximum depth of the bloom filters to use. This is a + /// tradeoff between the size of the parse meta and the speed of lookups. The + /// main reason to increase the depth is during generation there may be an + /// unresolvable collision at a certain depth, so we need to increase the + /// depth to resolve it. + /// @return parseMeta The parse meta built from the authoring meta and build + /// depth. function buildParseMetaV2(AuthoringMetaV2[] memory authoringMeta, uint8 maxDepth) internal pure @@ -178,6 +229,15 @@ library LibGenParseMeta { } } + /// @dev Builds a constant string containing the parse meta, which can be + /// used in generated code. The string also includes a comment describing the + /// structure of the parse meta for future reference. + /// @param vm The Vm instance to use for generating the constant string. + /// @param authoringMetaBytes The abi-encoded authoring meta to build the + /// parse meta from. + /// @param buildDepth The build depth to use for the parse meta. + /// @return A constant string containing the parse meta, with a comment + /// describing its structure. function parseMetaConstantString(Vm vm, bytes memory authoringMetaBytes, uint8 buildDepth) internal pure diff --git a/src/lib/deprecated/caller/LibDeployerDiscoverable.sol b/src/lib/deprecated/caller/LibDeployerDiscoverable.sol deleted file mode 100644 index f5c223c..0000000 --- a/src/lib/deprecated/caller/LibDeployerDiscoverable.sol +++ /dev/null @@ -1,26 +0,0 @@ -// SPDX-License-Identifier: LicenseRef-DCL-1.0 -// SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd -pragma solidity ^0.8.25; - -import {IExpressionDeployerV4} from "../../../interface/deprecated/IExpressionDeployerV4.sol"; -import {IInterpreterStoreV2} from "../../../interface/IInterpreterStoreV2.sol"; -import {IInterpreterV2} from "../../../interface/deprecated/IInterpreterV2.sol"; - -library LibDeployerDiscoverable { - /// Hack so that some deployer will emit an event with the sender as the - /// caller of `touchDeployer`. This MAY be needed by indexers such as - /// subgraph that can only index events from the first moment they are aware - /// of some contract. The deployer MUST be registered in ERC1820 registry - /// before it is touched, THEN the caller meta MUST be emitted after the - /// deployer is touched. This allows indexers such as subgraph to index the - /// deployer, then see the caller, then see the caller's meta emitted in the - /// same transaction. - /// This is NOT required if ANY other expression is deployed in the same - /// transaction as the caller meta, there only needs to be one expression on - /// ANY deployer known to ERC1820. - function touchDeployerV4(address deployer) internal { - (IInterpreterV2 interpreter, IInterpreterStoreV2 store, address expression, bytes memory io) = - IExpressionDeployerV4(deployer).deployExpression2("", new uint256[](0)); - (interpreter, store, expression, io); - } -} diff --git a/src/lib/deprecated/caller/LibEncodedDispatch.sol b/src/lib/deprecated/caller/LibEncodedDispatch.sol deleted file mode 100644 index 3589cc7..0000000 --- a/src/lib/deprecated/caller/LibEncodedDispatch.sol +++ /dev/null @@ -1,44 +0,0 @@ -// SPDX-License-Identifier: LicenseRef-DCL-1.0 -// SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd -pragma solidity ^0.8.25; - -import {SourceIndexV2, EncodedDispatch} from "../../../interface/deprecated/IInterpreterV2.sol"; - -/// @title LibEncodedDispatch -/// @notice Establishes and implements a convention for encoding an interpreter -/// dispatch. Handles encoding of several things required for efficient dispatch. -library LibEncodedDispatch { - /// Builds an `EncodedDispatch` from its constituent parts. - /// @param expression The onchain address of the expression to run. - /// @param sourceIndex The index of the source to run within the expression - /// as an entrypoint. - /// @param maxOutputs The maximum outputs the caller can meaningfully use. - /// If the interpreter returns a larger stack than this it is merely wasting - /// gas across the external call boundary. - /// @return The encoded dispatch. - function encode2(address expression, SourceIndexV2 sourceIndex, uint256 maxOutputs) - internal - pure - returns (EncodedDispatch) - { - // Both source index and max outputs are expected to be compile time - // constants, or at least significantly less than type(uint16).max. - // Generally a real world implementation would hit gas limits long before - // either of these values overflowed. Rather than add the gas of - // conditionals and errors to check for overflow, we simply truncate the - // values to uint16. - return EncodedDispatch.wrap( - (uint256(uint160(expression)) << 0x20) | (uint256(uint16(SourceIndexV2.unwrap(sourceIndex))) << 0x10) - // forge-lint: disable-next-line(unsafe-typecast) - | uint256(uint16(maxOutputs)) - ); - } - - function decode2(EncodedDispatch dispatch) internal pure returns (address, SourceIndexV2, uint256) { - return ( - address(uint160(EncodedDispatch.unwrap(dispatch) >> 0x20)), - SourceIndexV2.wrap(uint256(uint16(EncodedDispatch.unwrap(dispatch) >> 0x10))), - uint256(uint16(EncodedDispatch.unwrap(dispatch))) - ); - } -} diff --git a/src/lib/ns/LibNamespace.sol b/src/lib/ns/LibNamespace.sol index df662e7..3d139ff 100644 --- a/src/lib/ns/LibNamespace.sol +++ b/src/lib/ns/LibNamespace.sol @@ -2,8 +2,12 @@ // SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd pragma solidity ^0.8.25; -import {StateNamespace, FullyQualifiedNamespace} from "../../interface/IInterpreterV3.sol"; +import {StateNamespace, FullyQualifiedNamespace} from "../../interface/IInterpreterV4.sol"; +/// @title LibNamespace +/// @notice Conventions for working with namespaces as a calling contract. All of +/// this functionality is OPTIONAL but probably useful for the majority of +/// contracts as it enables safe (scoped) mutations in Rainlang. library LibNamespace { /// Standard way to elevate a caller-provided state namespace to a universal /// namespace that is disjoint from all other caller-provided namespaces. diff --git a/src/lib/parse/LibParseMeta.sol b/src/lib/parse/LibParseMeta.sol index 5d08143..8d03894 100644 --- a/src/lib/parse/LibParseMeta.sol +++ b/src/lib/parse/LibParseMeta.sol @@ -25,7 +25,23 @@ uint256 constant FINGERPRINT_MASK = 0xFFFFFF; /// @dev 33 = 32 bytes for expansion + 1 byte for seed uint256 constant META_EXPANSION_SIZE = 0x21; +/// @title LibParseMeta +/// @notice Common logic for working with parse meta, which is the data structure +/// used to store information about the words in a parser. The parse meta is +/// designed to be compact and efficient to lookup. library LibParseMeta { + /// @dev Given a word and a seed, return the bitmap and fingerprint for the + /// word. The bitmap is a uint256 with a single bit set, which can be used + /// to check if the word is present in an expansion. The fingerprint is a + /// uint256 with the low 3 bytes set, which can be used to check for + /// collisions when a word is found in an expansion. + /// @param seed The seed to use for the bitmap, which should be a byte value + /// between 0 and 255. + /// @param word The word to generate the bitmap and fingerprint for. + /// @return bitmap A uint256 with a single bit set, which can be used to + /// check if the word is present in an expansion. + /// @return hashed A uint256 with the low 3 bytes set, which can be used to + /// check for collisions when a word is found in an expansion. function wordBitmapped(uint256 seed, bytes32 word) internal pure returns (uint256 bitmap, uint256 hashed) { assembly ("memory-safe") { mstore(0, word) diff --git a/test/src/lib/caller/LibContextSlow.sol b/test/src/lib/caller/LibContextSlow.sol index 2db9524..a60e546 100644 --- a/test/src/lib/caller/LibContextSlow.sol +++ b/test/src/lib/caller/LibContextSlow.sol @@ -6,7 +6,7 @@ import {LibHashNoAlloc, HASH_NIL} from "rain.lib.hash/LibHashNoAlloc.sol"; import {LibCast} from "rain.lib.typecast/LibCast.sol"; import {LibUint256Array} from "rain.solmem/lib/LibUint256Array.sol"; -import {SignedContextV1} from "src/interface/IInterpreterCallerV3.sol"; +import {SignedContextV1} from "src/interface/IInterpreterCallerV4.sol"; library LibContextSlow { using LibUint256Array for uint256; diff --git a/test/src/lib/caller/LibDeployerDiscoverable.t.sol b/test/src/lib/caller/LibDeployerDiscoverable.t.sol deleted file mode 100644 index d4317a6..0000000 --- a/test/src/lib/caller/LibDeployerDiscoverable.t.sol +++ /dev/null @@ -1,29 +0,0 @@ -// SPDX-License-Identifier: LicenseRef-DCL-1.0 -// SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd -pragma solidity =0.8.25; - -import {Test} from "forge-std/Test.sol"; -import {IExpressionDeployerV4} from "src/interface/deprecated/IExpressionDeployerV4.sol"; -import {LibDeployerDiscoverable} from "src/lib/deprecated/caller/LibDeployerDiscoverable.sol"; -import {IInterpreterV2} from "src/interface/deprecated/IInterpreterV2.sol"; -import {IInterpreterStoreV2} from "src/interface/IInterpreterStoreV2.sol"; - -contract TestDeployerV4 is IExpressionDeployerV4 { - function deployExpression2(bytes memory, uint256[] memory) - external - returns (IInterpreterV2, IInterpreterStoreV2, address, bytes memory) - {} -} - -contract LibDeployerDiscoverableTest is Test { - /// MUST be possible to touch a deployer with 0 data to support discovery. - function testTouchDeployerV4Mock() external { - TestDeployerV4 deployer = new TestDeployerV4(); - vm.expectCall( - address(deployer), - abi.encodeWithSelector(IExpressionDeployerV4.deployExpression2.selector, "", new uint256[](0)), - 1 - ); - LibDeployerDiscoverable.touchDeployerV4(address(deployer)); - } -} diff --git a/test/src/lib/caller/LibEvaluable.t.sol b/test/src/lib/caller/LibEvaluable.t.sol index 9561f62..19415c3 100644 --- a/test/src/lib/caller/LibEvaluable.t.sol +++ b/test/src/lib/caller/LibEvaluable.t.sol @@ -3,134 +3,64 @@ pragma solidity =0.8.25; import {Test} from "forge-std/Test.sol"; -import {EvaluableV2} from "src/interface/deprecated/IInterpreterCallerV2.sol"; import {LibEvaluable} from "src/lib/caller/LibEvaluable.sol"; import {LibEvaluableSlow} from "./LibEvaluableSlow.sol"; -import {IInterpreterStoreV2} from "src/interface/IInterpreterStoreV2.sol"; -import {IInterpreterV2} from "src/interface/deprecated/IInterpreterV2.sol"; +import {IInterpreterStoreV3} from "src/interface/IInterpreterStoreV3.sol"; -import {EvaluableV3} from "src/interface/IInterpreterCallerV3.sol"; -import {IInterpreterV3} from "src/interface/IInterpreterV3.sol"; +import {EvaluableV4} from "src/interface/IInterpreterCallerV4.sol"; +import {IInterpreterV4} from "src/interface/IInterpreterV4.sol"; contract LibEvaluableTest is Test { - using LibEvaluable for EvaluableV2; - using LibEvaluable for EvaluableV3; + using LibEvaluable for EvaluableV4; /// Test a known hash so that if the hash function changes, we know. - function testEvaluableV2KnownHash() external pure { - EvaluableV2 memory evaluable = - EvaluableV2(IInterpreterV2(address(1)), IInterpreterStoreV2(address(2)), address(3)); - assertEq(evaluable.hash(), bytes32(0x6e0c627900b24bd432fe7b1f713f1b0744091a646a9fe4a65a18dfed21f2949c)); - } - - function testEvaluableV2HashDifferent(EvaluableV2 memory a, EvaluableV2 memory b) public pure { - vm.assume(a.interpreter != b.interpreter || a.store != b.store || a.expression != b.expression); - assertTrue(a.hash() != b.hash()); - } - - function testEvaluableV2HashSame(EvaluableV2 memory a) public pure { - EvaluableV2 memory b = EvaluableV2(a.interpreter, a.store, a.expression); - assertEq(a.hash(), b.hash()); - } - - function testEvaluableV2HashSensitivity(EvaluableV2 memory a, EvaluableV2 memory b) public pure { - vm.assume(a.interpreter != b.interpreter && a.store != b.store && a.expression != b.expression); - - EvaluableV2 memory c; - - assertTrue(a.hash() != b.hash()); - - // Check interpreter changes hash. - c = EvaluableV2(b.interpreter, a.store, a.expression); - assertTrue(a.hash() != c.hash()); - - // Check store changes hash. - c = EvaluableV2(a.interpreter, b.store, a.expression); - assertTrue(a.hash() != c.hash()); - - // Check expression changes hash. - c = EvaluableV2(a.interpreter, a.store, b.expression); - assertTrue(a.hash() != c.hash()); - - // Check match. - c = EvaluableV2(a.interpreter, a.store, a.expression); - assertEq(a.hash(), c.hash()); - - // Check hash doesn't include extraneous data - uint256 v0 = type(uint256).max; - uint256 v1 = 0; - EvaluableV2 memory d = EvaluableV2(IInterpreterV2(address(0)), IInterpreterStoreV2(address(0)), address(0)); - assembly ("memory-safe") { - mstore(mload(0x40), v0) - } - bytes32 hash0 = d.hash(); - assembly ("memory-safe") { - mstore(mload(0x40), v1) - } - bytes32 hash1 = d.hash(); - assertEq(hash0, hash1); - } - - function testEvaluableV2HashGas0() public pure { - EvaluableV2(IInterpreterV2(address(0)), IInterpreterStoreV2(address(0)), address(0)).hash(); - } - - function testEvaluableV2HashGasSlow0() public pure { - LibEvaluableSlow.hashSlow(EvaluableV2(IInterpreterV2(address(0)), IInterpreterStoreV2(address(0)), address(0))); - } - - function testEvaluableV2ReferenceImplementation(EvaluableV2 memory evaluable) public pure { - assertEq(LibEvaluable.hash(evaluable), LibEvaluableSlow.hashSlow(evaluable)); - } - - /// Test a known hash so that if the hash function changes, we know. - function testEvaluableV3KnownHash() external pure { - EvaluableV3 memory evaluable = - EvaluableV3(IInterpreterV3(address(1)), IInterpreterStoreV2(address(2)), hex"030405"); + function testEvaluableV4KnownHash() external pure { + EvaluableV4 memory evaluable = + EvaluableV4(IInterpreterV4(address(1)), IInterpreterStoreV3(address(2)), hex"030405"); assertEq(evaluable.hash(), bytes32(0x389371bb1206fa55c5ce170f501ebbe5aacd211e163a6076a349c8bc6437aaa9)); } - function testEvaluableV3HashDifferent(EvaluableV3 memory a, EvaluableV3 memory b) public pure { + function testEvaluableV4HashDifferent(EvaluableV4 memory a, EvaluableV4 memory b) public pure { vm.assume( a.interpreter != b.interpreter || a.store != b.store || keccak256(a.bytecode) != keccak256(b.bytecode) ); assertTrue(a.hash() != b.hash()); } - function testEvaluableV3HashSame(EvaluableV3 memory a) public pure { - EvaluableV3 memory b = EvaluableV3(a.interpreter, a.store, a.bytecode); + function testEvaluableV4HashSame(EvaluableV4 memory a) public pure { + EvaluableV4 memory b = EvaluableV4(a.interpreter, a.store, a.bytecode); assertEq(a.hash(), b.hash()); } - function testEvaluableV3HashSensitivity(EvaluableV3 memory a, EvaluableV3 memory b) public pure { + function testEvaluableV4HashSensitivity(EvaluableV4 memory a, EvaluableV4 memory b) public pure { vm.assume( a.interpreter != b.interpreter && a.store != b.store && keccak256(a.bytecode) != keccak256(b.bytecode) ); - EvaluableV3 memory c; + EvaluableV4 memory c; assertTrue(a.hash() != b.hash()); // Check interpreter changes hash. - c = EvaluableV3(b.interpreter, a.store, a.bytecode); + c = EvaluableV4(b.interpreter, a.store, a.bytecode); assertTrue(a.hash() != c.hash()); // Check store changes hash. - c = EvaluableV3(a.interpreter, b.store, a.bytecode); + c = EvaluableV4(a.interpreter, b.store, a.bytecode); assertTrue(a.hash() != c.hash()); // Check bytecode changes hash. - c = EvaluableV3(a.interpreter, a.store, b.bytecode); + c = EvaluableV4(a.interpreter, a.store, b.bytecode); assertTrue(a.hash() != c.hash()); // Check match. - c = EvaluableV3(a.interpreter, a.store, a.bytecode); + c = EvaluableV4(a.interpreter, a.store, a.bytecode); assertEq(a.hash(), c.hash()); // Check hash doesn't include extraneous data uint256 v0 = type(uint256).max; uint256 v1 = 0; - EvaluableV3 memory d = EvaluableV3(IInterpreterV3(address(0)), IInterpreterStoreV2(address(0)), hex""); + EvaluableV4 memory d = EvaluableV4(IInterpreterV4(address(0)), IInterpreterStoreV3(address(0)), hex""); assembly ("memory-safe") { mstore(mload(0x40), v0) } @@ -142,24 +72,24 @@ contract LibEvaluableTest is Test { assertEq(hash0, hash1); } - function testEvaluableV3HashGas0() public pure { - EvaluableV3(IInterpreterV3(address(0)), IInterpreterStoreV2(address(0)), hex"").hash(); + function testEvaluableV4HashGas0() public pure { + EvaluableV4(IInterpreterV4(address(0)), IInterpreterStoreV3(address(0)), hex"").hash(); } - function testEvaluableV3BytecodeLengthSensitivity() public pure { - EvaluableV3 memory a = EvaluableV3(IInterpreterV3(address(0)), IInterpreterStoreV2(address(0)), hex"01"); + function testEvaluableV4BytecodeLengthSensitivity() public pure { + EvaluableV4 memory a = EvaluableV4(IInterpreterV4(address(0)), IInterpreterStoreV3(address(0)), hex"01"); // `b` is identical to `a` except for the bytecode length. // Note the trailing `00` in the bytecode would be the same in memory as // the `00` padding that the allocator would add to `a`'s bytecode. - EvaluableV3 memory b = EvaluableV3(IInterpreterV3(address(0)), IInterpreterStoreV2(address(0)), hex"0100"); + EvaluableV4 memory b = EvaluableV4(IInterpreterV4(address(0)), IInterpreterStoreV3(address(0)), hex"0100"); assertTrue(a.hash() != b.hash()); } - function testEvaluableV3HashGasSlow0() public pure { - LibEvaluableSlow.hashSlow(EvaluableV3(IInterpreterV3(address(0)), IInterpreterStoreV2(address(0)), hex"")); + function testEvaluableV4HashGasSlow0() public pure { + LibEvaluableSlow.hashSlow(EvaluableV4(IInterpreterV4(address(0)), IInterpreterStoreV3(address(0)), hex"")); } - function testEvaluableV3ReferenceImplementation(EvaluableV3 memory evaluable) public pure { + function testEvaluableV4ReferenceImplementation(EvaluableV4 memory evaluable) public pure { assertEq(LibEvaluable.hash(evaluable), LibEvaluableSlow.hashSlow(evaluable)); } } diff --git a/test/src/lib/caller/LibEvaluableSlow.sol b/test/src/lib/caller/LibEvaluableSlow.sol index 1a44490..ff13b0e 100644 --- a/test/src/lib/caller/LibEvaluableSlow.sol +++ b/test/src/lib/caller/LibEvaluableSlow.sol @@ -2,8 +2,8 @@ // SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd pragma solidity =0.8.25; -import {EvaluableV2} from "src/interface/deprecated/IInterpreterCallerV2.sol"; -import {EvaluableV3} from "src/interface/IInterpreterCallerV3.sol"; +import {EvaluableV2} from "src/interface/deprecated/v1/IInterpreterCallerV2.sol"; +import {EvaluableV4} from "src/interface/IInterpreterCallerV4.sol"; library LibEvaluableSlow { function hashSlow(EvaluableV2 memory evaluable) internal pure returns (bytes32) { @@ -16,7 +16,7 @@ library LibEvaluableSlow { ); } - function hashSlow(EvaluableV3 memory evaluable) internal pure returns (bytes32) { + function hashSlow(EvaluableV4 memory evaluable) internal pure returns (bytes32) { return keccak256( abi.encodePacked( keccak256( diff --git a/test/src/lib/deprecated/caller/LibEncodedDispatch.t.sol b/test/src/lib/deprecated/caller/LibEncodedDispatch.t.sol deleted file mode 100644 index 6c6422f..0000000 --- a/test/src/lib/deprecated/caller/LibEncodedDispatch.t.sol +++ /dev/null @@ -1,18 +0,0 @@ -// SPDX-License-Identifier: LicenseRef-DCL-1.0 -// SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd -pragma solidity =0.8.25; - -import {Test} from "forge-std/Test.sol"; -import {LibEncodedDispatch} from "src/lib/deprecated/caller/LibEncodedDispatch.sol"; -import {SourceIndexV2} from "src/interface/IInterpreterV3.sol"; - -contract LibEncodedDispatchTest is Test { - function testRoundTrip(address expression, SourceIndexV2 sourceIndex, uint16 maxOutputs) public pure { - sourceIndex = SourceIndexV2.wrap(bound(SourceIndexV2.unwrap(sourceIndex), 0, type(uint16).max)); - (address expressionDecoded, SourceIndexV2 sourceIndexDecoded, uint256 maxOutputsDecoded) = - LibEncodedDispatch.decode2(LibEncodedDispatch.encode2(expression, sourceIndex, maxOutputs)); - assertEq(expression, expressionDecoded); - assertEq(SourceIndexV2.unwrap(sourceIndex), SourceIndexV2.unwrap(sourceIndexDecoded)); - assertEq(maxOutputs, maxOutputsDecoded); - } -} diff --git a/test/src/lib/ns/LibNamespaceSlow.sol b/test/src/lib/ns/LibNamespaceSlow.sol index 1333807..8323e83 100644 --- a/test/src/lib/ns/LibNamespaceSlow.sol +++ b/test/src/lib/ns/LibNamespaceSlow.sol @@ -2,7 +2,7 @@ // SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd pragma solidity =0.8.25; -import {StateNamespace, FullyQualifiedNamespace} from "src/interface/IInterpreterV3.sol"; +import {StateNamespace, FullyQualifiedNamespace} from "src/interface/IInterpreterV4.sol"; library LibNamespaceSlow { /// Implements an abi encoding based version of `qualifyNamespace` that is