Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
N
nebula
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
exchain
nebula
Commits
21678e30
Commit
21678e30
authored
Jun 14, 2023
by
clabby
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
perf: Pack clock & position
parent
d2933a35
Changes
6
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
69 additions
and
69 deletions
+69
-69
.gas-snapshot
packages/contracts-bedrock/.gas-snapshot
+3
-3
LibClock.sol
...ages/contracts-bedrock/contracts/dispute/lib/LibClock.sol
+5
-5
LibPosition.sol
...s/contracts-bedrock/contracts/dispute/lib/LibPosition.sol
+23
-23
DisputeTypes.sol
...es/contracts-bedrock/contracts/libraries/DisputeTypes.sol
+6
-6
LibClock.t.sol
packages/contracts-bedrock/contracts/test/LibClock.t.sol
+6
-6
LibPosition.t.sol
packages/contracts-bedrock/contracts/test/LibPosition.t.sol
+26
-26
No files found.
packages/contracts-bedrock/.gas-snapshot
View file @
21678e30
...
...
@@ -36,9 +36,9 @@ FaultDisputeGame_Test:test_extraData_succeeds() (gas: 17456)
FaultDisputeGame_Test:test_gameData_succeeds() (gas: 17882)
FaultDisputeGame_Test:test_gameStart_succeeds() (gas: 10315)
FaultDisputeGame_Test:test_gameType_succeeds() (gas: 8237)
FaultDisputeGame_Test:test_initialRootClaimData_succeeds() (gas: 1
952
2)
FaultDisputeGame_Test:test_rootClaim_succeeds() (gas: 82
25
)
FaultDisputeGame_Test:test_simpleAttack_succeeds() (gas: 1
29033
)
FaultDisputeGame_Test:test_initialRootClaimData_succeeds() (gas: 1
760
2)
FaultDisputeGame_Test:test_rootClaim_succeeds() (gas: 82
13
)
FaultDisputeGame_Test:test_simpleAttack_succeeds() (gas: 1
05905
)
FaultDisputeGame_Test:test_version_succeeds() (gas: 9736)
FeeVault_Test:test_constructor_succeeds() (gas: 18185)
GasBenchMark_L1CrossDomainMessenger:test_sendMessage_benchmark_0() (gas: 352135)
...
...
packages/contracts-bedrock/contracts/dispute/lib/LibClock.sol
View file @
21678e30
...
...
@@ -16,7 +16,7 @@ library LibClock {
*/
function wrap(Duration _duration, Timestamp _timestamp) internal pure returns (Clock _clock) {
assembly {
_clock := or(shl(0x
8
0, _duration), _timestamp)
_clock := or(shl(0x
4
0, _duration), _timestamp)
}
}
...
...
@@ -26,9 +26,9 @@ library LibClock {
* @return _duration The `Duration` pulled out of `_clock`.
*/
function duration(Clock _clock) internal pure returns (Duration _duration) {
// Shift the high-order
128 bits into the low-order 128
bits, leaving only the `duration`.
// Shift the high-order
64 bits into the low-order 64
bits, leaving only the `duration`.
assembly {
_duration := shr(0x
8
0, _clock)
_duration := shr(0x
4
0, _clock)
}
}
...
...
@@ -38,10 +38,10 @@ library LibClock {
* @return _timestamp The `Timestamp` pulled out of `_clock`.
*/
function timestamp(Clock _clock) internal pure returns (Timestamp _timestamp) {
// Clean the high-order 1
28
bits by shifting the clock left and then right again, leaving
// Clean the high-order 1
92
bits by shifting the clock left and then right again, leaving
// only the `timestamp`.
assembly {
_timestamp := shr(0x
80, shl(0x8
0, _clock))
_timestamp := shr(0x
C0, shl(0xC
0, _clock))
}
}
}
packages/contracts-bedrock/contracts/dispute/lib/LibPosition.sol
View file @
21678e30
...
...
@@ -8,30 +8,30 @@ import "../../libraries/DisputeTypes.sol";
* @notice This library contains helper functions for working with the `Position` type.
*/
library LibPosition {
function wrap(uint
128 _depth, uint128
_indexAtDepth) internal pure returns (Position _position) {
function wrap(uint
64 _depth, uint64
_indexAtDepth) internal pure returns (Position _position) {
assembly {
_position := or(shl(0x
8
0, _depth), _indexAtDepth)
_position := or(shl(0x
4
0, _depth), _indexAtDepth)
}
}
/**
* @notice Pulls the `depth` out of a packed `Position` type.
*/
function depth(Position position) internal pure returns (uint
128
_depth) {
// Shift the high-order
128 bits into the low-order 128
bits, leaving only the `depth`.
function depth(Position position) internal pure returns (uint
64
_depth) {
// Shift the high-order
64 bits into the low-order 64
bits, leaving only the `depth`.
assembly {
_depth := shr(0x
8
0, position)
_depth := shr(0x
4
0, position)
}
}
/**
* @notice Pulls the `indexAtDepth` out of a packed `Position` type.
*/
function indexAtDepth(Position position) internal pure returns (uint
128
_indexAtDepth) {
// Clean the high-order 1
28
bits by shifting the position left and then right again, leaving
function indexAtDepth(Position position) internal pure returns (uint
64
_indexAtDepth) {
// Clean the high-order 1
92
bits by shifting the position left and then right again, leaving
// only the `indexAtDepth`.
assembly {
_indexAtDepth := shr(0x
80, shl(0x8
0, position))
_indexAtDepth := shr(0x
C0, shl(0xC
0, position))
}
}
...
...
@@ -41,12 +41,12 @@ library LibPosition {
* @return _left The position to the left of `position`.
*/
function left(Position position) internal pure returns (Position _left) {
uint
128
_depth = depth(position);
uint
128
_indexAtDepth = indexAtDepth(position);
uint
64
_depth = depth(position);
uint
64
_indexAtDepth = indexAtDepth(position);
// Left = { depth: position.depth + 1, indexAtDepth: position.indexAtDepth * 2 }
assembly {
_left := or(shl(0x
8
0, add(_depth, 0x01)), shl(0x01, _indexAtDepth))
_left := or(shl(0x
4
0, add(_depth, 0x01)), shl(0x01, _indexAtDepth))
}
}
...
...
@@ -56,12 +56,12 @@ library LibPosition {
* @return _right The position to the right of `position`.
*/
function right(Position position) internal pure returns (Position _right) {
uint
128
_depth = depth(position);
uint
128
_indexAtDepth = indexAtDepth(position);
uint
64
_depth = depth(position);
uint
64
_indexAtDepth = indexAtDepth(position);
// Right = { depth: position.depth + 1, indexAtDepth: position.indexAtDepth * 2 + 1 }
assembly {
_right := or(shl(0x
8
0, add(_depth, 0x01)), add(shl(0x01, _indexAtDepth), 0x01))
_right := or(shl(0x
4
0, add(_depth, 0x01)), add(shl(0x01, _indexAtDepth), 0x01))
}
}
...
...
@@ -71,12 +71,12 @@ library LibPosition {
* @return _parent The parent position of `position`.
*/
function parent(Position position) internal pure returns (Position _parent) {
uint
128
_depth = depth(position);
uint
128
_indexAtDepth = indexAtDepth(position);
uint
64
_depth = depth(position);
uint
64
_indexAtDepth = indexAtDepth(position);
// Parent = { depth: position.depth - 1, indexAtDepth: position.indexAtDepth / 2 }
assembly {
_parent := or(shl(0x
8
0, sub(_depth, 0x01)), shr(0x01, _indexAtDepth))
_parent := or(shl(0x
4
0, sub(_depth, 0x01)), shr(0x01, _indexAtDepth))
}
}
...
...
@@ -87,12 +87,12 @@ library LibPosition {
* @return _rightIndex The deepest, right most index relative to the `position`.
* TODO: Optimize; No need to update the full position in the sub loop.
*/
function rightIndex(Position position, uint256 maxDepth) internal pure returns (uint
128
_rightIndex) {
function rightIndex(Position position, uint256 maxDepth) internal pure returns (uint
64
_rightIndex) {
assembly {
_rightIndex := shr(0x
80, shl(0x8
0, position))
_rightIndex := shr(0x
C0, shl(0xC
0, position))
// Walk down to the max depth by moving right
for { let i := shr(0x
8
0, position) } lt(i, sub(maxDepth, 0x01)) { i := add(i, 0x01) } {
for { let i := shr(0x
4
0, position) } lt(i, sub(maxDepth, 0x01)) { i := add(i, 0x01) } {
_rightIndex := add(0x01, shl(0x01, _rightIndex))
}
}
...
...
@@ -109,12 +109,12 @@ library LibPosition {
* @notice Get the defend position of `position`.
*/
function defend(Position position) internal pure returns (Position _defend) {
uint
128
_depth = depth(position);
uint
128
_indexAtDepth = indexAtDepth(position);
uint
64
_depth = depth(position);
uint
64
_indexAtDepth = indexAtDepth(position);
// Defend = { depth: position.depth + 1, indexAtDepth: ((position.indexAtDepth / 2) * 2 + 1) * 2 }
assembly {
_defend := or(shl(0x
8
0, add(_depth, 0x01)), shl(0x01, add(0x01, shl(0x01, shr(0x01, _indexAtDepth)))))
_defend := or(shl(0x
4
0, add(_depth, 0x01)), shl(0x01, add(0x01, shl(0x01, shr(0x01, _indexAtDepth)))))
}
}
}
packages/contracts-bedrock/contracts/libraries/DisputeTypes.sol
View file @
21678e30
...
...
@@ -39,11 +39,11 @@ type Duration is uint64;
* ┌────────────┬────────────────┐
* │ Bits │ Value │
* ├────────────┼────────────────┤
* │ [0,
128)
│ Duration │
* │ [
128, 256)
│ Timestamp │
* │ [0,
64)
│ Duration │
* │ [
64, 128)
│ Timestamp │
* └────────────┴────────────────┘
*/
type Clock is uint
256
;
type Clock is uint
128
;
/**
* @notice A `Position` represents a position of a claim within the game tree.
...
...
@@ -51,11 +51,11 @@ type Clock is uint256;
* ┌────────────┬────────────────┐
* │ Bits │ Value │
* ├────────────┼────────────────┤
* │ [0,
128)
│ Depth │
* │ [
128, 256)
│ Index at depth │
* │ [0,
64)
│ Depth │
* │ [
64, 128)
│ Index at depth │
* └────────────┴────────────────┘
*/
type Position is uint
256
;
type Position is uint
128
;
/**
* @notice A `GameType` represents the type of game being played.
...
...
packages/contracts-bedrock/contracts/test/LibClock.t.sol
View file @
21678e30
...
...
@@ -12,16 +12,16 @@ contract LibClock_Test is Test {
/**
* @notice Tests that the `duration` function correctly shifts out the `Duration` from a packed `Clock` type.
*/
function testFuzz_duration_succeeds(
uint64 _duration, uint64
_timestamp) public {
Clock clock = LibClock.wrap(
Duration.wrap(_duration), Timestamp.wrap(_timestamp)
);
assertEq(Duration.unwrap(LibClock.duration(clock)),
_duration
);
function testFuzz_duration_succeeds(
Duration _duration, Timestamp
_timestamp) public {
Clock clock = LibClock.wrap(
_duration, _timestamp
);
assertEq(Duration.unwrap(LibClock.duration(clock)),
Duration.unwrap(_duration)
);
}
/**
* @notice Tests that the `timestamp` function correctly shifts out the `Timestamp` from a packed `Clock` type.
*/
function testFuzz_timestamp_succeeds(
uint64 _duration, uint64
_timestamp) public {
Clock clock = LibClock.wrap(
Duration.wrap(_duration), Timestamp.wrap(_timestamp)
);
assertEq(Timestamp.unwrap(LibClock.timestamp(clock)),
_timestamp
);
function testFuzz_timestamp_succeeds(
Duration _duration, Timestamp
_timestamp) public {
Clock clock = LibClock.wrap(
_duration, _timestamp
);
assertEq(Timestamp.unwrap(LibClock.timestamp(clock)),
Timestamp.unwrap(_timestamp)
);
}
}
packages/contracts-bedrock/contracts/test/LibPosition.t.sol
View file @
21678e30
...
...
@@ -10,16 +10,16 @@ import "../libraries/DisputeTypes.sol";
*/
contract LibPosition_Test is Test {
/**
* @dev Assumes a MAX depth of
127
for the Position type. Any greater depth can cause overflows.
* @dev At the lowest level of the tree, this allows for 2 **
127
leaves. In reality, the max game depth
* @dev Assumes a MAX depth of
63
for the Position type. Any greater depth can cause overflows.
* @dev At the lowest level of the tree, this allows for 2 **
63
leaves. In reality, the max game depth
* will likely be much lower.
*/
uint8 internal constant MAX_DEPTH =
127
;
uint8 internal constant MAX_DEPTH =
63
;
/**
* @notice Tests that the `depth` function correctly shifts out the `depth` from a packed `Position` type.
*/
function testFuzz_depth_correctness(uint
128 _depth, uint128
_indexAtDepth) public {
function testFuzz_depth_correctness(uint
64 _depth, uint64
_indexAtDepth) public {
Position position = LibPosition.wrap(_depth, _indexAtDepth);
assertEq(LibPosition.depth(position), _depth);
}
...
...
@@ -27,7 +27,7 @@ contract LibPosition_Test is Test {
/**
* @notice Tests that the `indexAtDepth` function correctly shifts out the `indexAtDepth` from a packed `Position` type.
*/
function testFuzz_indexAtDepth_correctness(uint
128 _depth, uint128
_indexAtDepth) public {
function testFuzz_indexAtDepth_correctness(uint
64 _depth, uint64
_indexAtDepth) public {
Position position = LibPosition.wrap(_depth, _indexAtDepth);
assertEq(LibPosition.indexAtDepth(position), _indexAtDepth);
}
...
...
@@ -35,27 +35,27 @@ contract LibPosition_Test is Test {
/**
* @notice Tests that the `left` function correctly computes the position of the left child.
*/
function testFuzz_left_correctness(uint8 _depth, uint
128
_indexAtDepth) public {
// Depth bound: [0,
127
]
function testFuzz_left_correctness(uint8 _depth, uint
64
_indexAtDepth) public {
// Depth bound: [0,
63
]
_depth = uint8(bound(_depth, 0, MAX_DEPTH));
// Index at depth bound: [0, 2 ** _depth]
_indexAtDepth = uint
128
(bound(_indexAtDepth, 0, 2**_depth));
_indexAtDepth = uint
64
(bound(_indexAtDepth, 0, 2**_depth));
Position position = LibPosition.wrap(_depth, _indexAtDepth);
Position left = LibPosition.left(position);
assertEq(LibPosition.depth(left), uint
128
(_depth) + 1);
assertEq(LibPosition.depth(left), uint
64
(_depth) + 1);
assertEq(LibPosition.indexAtDepth(left), _indexAtDepth * 2);
}
/**
* @notice Tests that the `right` function correctly computes the position of the right child.
*/
function testFuzz_right_correctness(uint8 _depth, uint
128
_indexAtDepth) public {
// Depth bound: [0,
127
]
function testFuzz_right_correctness(uint8 _depth, uint
64
_indexAtDepth) public {
// Depth bound: [0,
63
]
_depth = uint8(bound(_depth, 0, MAX_DEPTH));
// Index at depth bound: [0, 2 ** _depth]
_indexAtDepth = uint
128
(bound(_indexAtDepth, 0, 2**_depth));
_indexAtDepth = uint
64
(bound(_indexAtDepth, 0, 2**_depth));
Position position = LibPosition.wrap(_depth, _indexAtDepth);
Position right = LibPosition.right(position);
...
...
@@ -67,11 +67,11 @@ contract LibPosition_Test is Test {
/**
* @notice Tests that the `parent` function correctly computes the position of the parent.
*/
function testFuzz_parent_correctness(uint8 _depth, uint
128
_indexAtDepth) public {
// Depth bound: [1,
127
]
function testFuzz_parent_correctness(uint8 _depth, uint
64
_indexAtDepth) public {
// Depth bound: [1,
63
]
_depth = uint8(bound(_depth, 1, MAX_DEPTH));
// Index at depth bound: [0, 2 ** _depth]
_indexAtDepth = uint
128
(bound(_indexAtDepth, 0, 2**_depth));
_indexAtDepth = uint
64
(bound(_indexAtDepth, 0, 2**_depth));
Position position = LibPosition.wrap(_depth, _indexAtDepth);
Position parent = LibPosition.parent(position);
...
...
@@ -87,24 +87,24 @@ contract LibPosition_Test is Test {
function testFuzz_rightIndex_correctness(
uint8 _maxDepth,
uint8 _depth,
uint
128
_indexAtDepth
uint
64
_indexAtDepth
) public {
// Max depth bound: [1,
127
]
// Max depth bound: [1,
63
]
// The max game depth MUST be at least 1.
_maxDepth = uint8(bound(_maxDepth, 1, MAX_DEPTH));
// Depth bound: [0, _maxDepth]
_depth = uint8(bound(_depth, 0, _maxDepth));
// Index at depth bound: [0, 2 ** _depth]
_indexAtDepth = uint
128
(bound(_indexAtDepth, 0, 2**_depth));
_indexAtDepth = uint
64
(bound(_indexAtDepth, 0, 2**_depth));
Position position = LibPosition.wrap(_depth, _indexAtDepth);
uint
128
rightIndex = LibPosition.rightIndex(position, _maxDepth);
uint
64
rightIndex = LibPosition.rightIndex(position, _maxDepth);
// Find the deepest, rightmost index in Solidity rather than Yul
for (uint256 i = _depth; i < _maxDepth - 1; ++i) {
position = LibPosition.right(position);
}
uint
128
_rightIndex = LibPosition.indexAtDepth(position);
uint
64
_rightIndex = LibPosition.indexAtDepth(position);
assertEq(rightIndex, _rightIndex);
}
...
...
@@ -114,11 +114,11 @@ contract LibPosition_Test is Test {
* a given position.
* @dev `attack` is an alias for `left`, but we test it separately for completeness.
*/
function testFuzz_attack_correctness(uint8 _depth, uint
128
_indexAtDepth) public {
// Depth bound: [0,
127
]
function testFuzz_attack_correctness(uint8 _depth, uint
64
_indexAtDepth) public {
// Depth bound: [0,
63
]
_depth = uint8(bound(_depth, 0, MAX_DEPTH));
// Index at depth bound: [0, 2 ** _depth]
_indexAtDepth = uint
128
(bound(_indexAtDepth, 0, 2**_depth));
_indexAtDepth = uint
64
(bound(_indexAtDepth, 0, 2**_depth));
Position position = LibPosition.wrap(_depth, _indexAtDepth);
Position attack = LibPosition.attack(position);
...
...
@@ -133,11 +133,11 @@ contract LibPosition_Test is Test {
* @dev A defense can only be given if the position does not belong to the root claim, hence the bound of [1, 127]
* on the depth.
*/
function testFuzz_defend_correctness(uint8 _depth, uint
128
_indexAtDepth) public {
// Depth bound: [1,
127
]
function testFuzz_defend_correctness(uint8 _depth, uint
64
_indexAtDepth) public {
// Depth bound: [1,
63
]
_depth = uint8(bound(_depth, 1, MAX_DEPTH));
// Index at depth bound: [0, 2 ** _depth]
_indexAtDepth = uint
128
(bound(_indexAtDepth, 0, 2**_depth));
_indexAtDepth = uint
64
(bound(_indexAtDepth, 0, 2**_depth));
Position position = LibPosition.wrap(_depth, _indexAtDepth);
Position defend = LibPosition.defend(position);
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment