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
72c6fb0a
Unverified
Commit
72c6fb0a
authored
Jun 21, 2023
by
clabby
Committed by
GitHub
Jun 21, 2023
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #6081 from ethereum-optimism/clabby/dispute/libpos-updates
chore(ctb): `LibPosition` documentation, tests, perf
parents
6d07c4d6
1c8a9f59
Changes
5
Show whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
339 additions
and
82 deletions
+339
-82
.gas-snapshot
packages/contracts-bedrock/.gas-snapshot
+23
-22
FaultDisputeGame.sol
.../contracts-bedrock/contracts/dispute/FaultDisputeGame.sol
+2
-2
LibPosition.sol
...s/contracts-bedrock/contracts/dispute/lib/LibPosition.sol
+37
-37
FaultDisputeGame.t.sol
...s/contracts-bedrock/contracts/test/FaultDisputeGame.t.sol
+11
-11
LibPosition.t.sol
packages/contracts-bedrock/contracts/test/LibPosition.t.sol
+266
-10
No files found.
packages/contracts-bedrock/.gas-snapshot
View file @
72c6fb0a
...
...
@@ -32,30 +32,30 @@ DisputeGameFactory_SetImplementation_Test:test_setImplementation_notOwner_revert
DisputeGameFactory_SetImplementation_Test:test_setImplementation_succeeds() (gas: 44243)
DisputeGameFactory_TransferOwnership_Test:test_transferOwnership_notOwner_reverts() (gas: 15950)
DisputeGameFactory_TransferOwnership_Test:test_transferOwnership_succeeds() (gas: 18642)
FaultDisputeGame_ResolvesCorrectly_CorrectRoot2:test_resolvesCorrectly_succeeds() (gas: 498304)
FaultDisputeGame_ResolvesCorrectly_CorrectRoot4:test_resolvesCorrectly_succeeds() (gas: 500038)
FaultDisputeGame_ResolvesCorrectly_CorrectRoot:test_resolvesCorrectly_succeeds() (gas: 490057)
FaultDisputeGame_ResolvesCorrectly_IncorrectRoot2:test_resolvesCorrectly_succeeds() (gas: 495173)
FaultDisputeGame_ResolvesCorrectly_IncorrectRoot3:test_resolvesCorrectly_succeeds() (gas: 496907)
FaultDisputeGame_ResolvesCorrectly_IncorrectRoot:test_resolvesCorrectly_succeeds() (gas: 486926)
FaultDisputeGame_Test:test_clockTimeExceeded_reverts() (gas: 26444)
FaultDisputeGame_Test:test_defendRoot_reverts() (gas: 13281)
FaultDisputeGame_Test:test_duplicateClaim_reverts() (gas: 103343)
FaultDisputeGame_Test:test_extraData_succeeds() (gas: 17431)
FaultDisputeGame_ResolvesCorrectly_CorrectRoot2:test_resolvesCorrectly_succeeds() (gas: 497198)
FaultDisputeGame_ResolvesCorrectly_CorrectRoot4:test_resolvesCorrectly_succeeds() (gas: 499064)
FaultDisputeGame_ResolvesCorrectly_CorrectRoot:test_resolvesCorrectly_succeeds() (gas: 489092)
FaultDisputeGame_ResolvesCorrectly_IncorrectRoot2:test_resolvesCorrectly_succeeds() (gas: 494067)
FaultDisputeGame_ResolvesCorrectly_IncorrectRoot3:test_resolvesCorrectly_succeeds() (gas: 495933)
FaultDisputeGame_ResolvesCorrectly_IncorrectRoot:test_resolvesCorrectly_succeeds() (gas: 485961)
FaultDisputeGame_Test:test_defendRoot_invalidMove_reverts() (gas: 13250)
FaultDisputeGame_Test:test_extraData_succeeds() (gas: 17409)
FaultDisputeGame_Test:test_gameData_succeeds() (gas: 17834)
FaultDisputeGame_Test:test_gameDepthExceeded_reverts() (gas: 408128)
FaultDisputeGame_Test:test_gameStart_succeeds() (gas: 10359)
FaultDisputeGame_Test:test_gameType_succeeds() (gas: 8281)
FaultDisputeGame_Test:test_initialRootClaimData_succeeds() (gas: 17669)
FaultDisputeGame_Test:test_moveAgainstNonexistentParent_reverts() (gas: 24611)
FaultDisputeGame_Test:test_move_gameNotInProgress_reverts() (gas: 10901)
FaultDisputeGame_Test:test_resolve_challengeContested() (gas: 221222)
FaultDisputeGame_Test:test_gameStart_succeeds() (gas: 10337)
FaultDisputeGame_Test:test_gameType_succeeds() (gas: 8216)
FaultDisputeGame_Test:test_initialRootClaimData_succeeds() (gas: 17691)
FaultDisputeGame_Test:test_move_clockTimeExceeded_reverts() (gas: 26410)
FaultDisputeGame_Test:test_move_duplicateClaim_reverts() (gas: 103231)
FaultDisputeGame_Test:test_move_gameDepthExceeded_reverts() (gas: 407967)
FaultDisputeGame_Test:test_move_gameNotInProgress_reverts() (gas: 10923)
FaultDisputeGame_Test:test_move_nonExistentParent_reverts() (gas: 24632)
FaultDisputeGame_Test:test_resolve_challengeContested() (gas: 221074)
FaultDisputeGame_Test:test_resolve_notInProgress_reverts() (gas: 9657)
FaultDisputeGame_Test:test_resolve_rootContested() (gas: 1061
44
)
FaultDisputeGame_Test:test_resolve_rootUncontested() (gas: 236
97
)
FaultDisputeGame_Test:test_resolve_teamDeathmatch() (gas: 391
960
)
FaultDisputeGame_Test:test_rootClaim_succeeds() (gas: 82
25
)
FaultDisputeGame_Test:test_simpleAttack_succeeds() (gas: 107
438
)
FaultDisputeGame_Test:test_resolve_rootContested() (gas: 1061
20
)
FaultDisputeGame_Test:test_resolve_rootUncontested() (gas: 236
30
)
FaultDisputeGame_Test:test_resolve_teamDeathmatch() (gas: 391
731
)
FaultDisputeGame_Test:test_rootClaim_succeeds() (gas: 82
03
)
FaultDisputeGame_Test:test_simpleAttack_succeeds() (gas: 107
322
)
FeeVault_Test:test_constructor_succeeds() (gas: 18185)
GasBenchMark_L1CrossDomainMessenger:test_sendMessage_benchmark_0() (gas: 352135)
GasBenchMark_L1CrossDomainMessenger:test_sendMessage_benchmark_1() (gas: 2950342)
...
...
@@ -230,6 +230,7 @@ LegacyERC20ETH_Test:test_mint_doesNotExist_reverts() (gas: 10627)
LegacyERC20ETH_Test:test_transferFrom_doesNotExist_reverts() (gas: 12957)
LegacyERC20ETH_Test:test_transfer_doesNotExist_reverts() (gas: 10755)
LegacyMessagePasser_Test:test_passMessageToL1_succeeds() (gas: 34524)
LibPosition_Test:test_pos_correctness_succeeds() (gas: 38711)
MerkleTrie_get_Test:test_get_corruptedProof_reverts() (gas: 5736)
MerkleTrie_get_Test:test_get_extraProofElements_reverts() (gas: 58975)
MerkleTrie_get_Test:test_get_invalidDataRemainder_reverts() (gas: 35852)
...
...
packages/contracts-bedrock/contracts/dispute/FaultDisputeGame.sol
View file @
72c6fb0a
...
...
@@ -123,7 +123,7 @@ contract FaultDisputeGame is IFaultDisputeGame, Clone {
// Pull the parent position out of storage.
Position parentPos = parent.position;
// Determine the position of the step.
Position stepPos =
_isAttack ? parentPos.attack() : parentPos.defend(
);
Position stepPos =
parentPos.move(_isAttack
);
// Ensure that the step position is 1 deeper than the maximum game depth.
if (stepPos.depth() != MAX_GAME_DEPTH + 1) {
...
...
@@ -214,7 +214,7 @@ contract FaultDisputeGame is IFaultDisputeGame, Clone {
// Compute the position that the claim commits to. Because the parent's position is already
// known, we can compute the next position by moving left or right depending on whether
// or not the move is an attack or defense.
Position nextPosition =
_isAttack ? parent.position.attack() : parent.position.defend(
);
Position nextPosition =
parent.position.move(_isAttack
);
// At the leaf nodes of the game, the only option is to run a step to prove or disprove
// the above claim. At this depth, the parent claim commits to the state after a single
...
...
packages/contracts-bedrock/contracts/dispute/lib/LibPosition.sol
View file @
72c6fb0a
...
...
@@ -8,20 +8,27 @@ import "../../libraries/DisputeTypes.sol";
* @notice This library contains helper functions for working with the `Position` type.
*/
library LibPosition {
/**
* @notice Computes a generalized index (2^{depth} + indexAtDepth).
* @param _depth The depth of the position.
* @param _indexAtDepth The index at the depth of the position.
* @return position_ The computed generalized index.
*/
function wrap(uint64 _depth, uint64 _indexAtDepth) internal pure returns (Position position_) {
assembly {
// gindex = 2^{_depth} + _indexAtDepth
position_ := add(shl(_depth, 1), _indexAtDepth)
}
}
/**
* @notice Pulls the `depth` out of a
packed
`Position` type.
* @param _position The
position
to get the `depth` of.
* @return depth_ The `depth` of the `position`.
* @notice Pulls the `depth` out of a `Position` type.
* @param _position The
generalized index
to get the `depth` of.
* @return depth_ The `depth` of the `position`
gindex
.
* @custom:attribution Solady <https://github.com/Vectorized/Solady>
*/
function depth(Position _position) internal pure returns (uint64 depth_) {
// Return the most significant bit
position
// Return the most significant bit
offset, which signifies the depth of the gindex.
assembly {
depth_ := or(depth_, shl(6, lt(0xffffffffffffffff, shr(depth_, _position))))
depth_ := or(depth_, shl(5, lt(0xffffffff, shr(depth_, _position))))
...
...
@@ -45,12 +52,16 @@ library LibPosition {
}
/**
* @notice Pulls the `indexAtDepth` out of a packed `Position` type.
* @param _position The position to get the `indexAtDepth` of.
* @return indexAtDepth_ The `indexAtDepth` of the `position`.
* @notice Pulls the `indexAtDepth` out of a `Position` type.
* The `indexAtDepth` is the left/right index of a position at a specific depth within
* the binary tree, starting from index 0. For example, at gindex 2, the `depth` = 1
* and the `indexAtDepth` = 0.
* @param _position The generalized index to get the `indexAtDepth` of.
* @return indexAtDepth_ The `indexAtDepth` of the `position` gindex.
*/
function indexAtDepth(Position _position) internal pure returns (uint64 indexAtDepth_) {
// Return bits p_{msb-1}...p_{0}
// Return bits p_{msb-1}...p_{0}. This effectively pulls the 2^{depth} out of the gindex,
// leaving only the `indexAtDepth`.
uint256 msb = depth(_position);
assembly {
indexAtDepth_ := sub(_position, shl(msb, 1))
...
...
@@ -58,7 +69,7 @@ library LibPosition {
}
/**
* @notice Get the
position to the left of `
position`.
* @notice Get the
left child of `_
position`.
* @param _position The position to get the left position of.
* @return left_ The position to the left of `position`.
*/
...
...
@@ -69,18 +80,18 @@ library LibPosition {
}
/**
* @notice Get the
position to the right of `position`.
* @notice Get the
right child of `_position`
* @param _position The position to get the right position of.
* @return right_ The position to the right of `position`.
*/
function right(Position _position) internal pure returns (Position right_) {
assembly {
right_ :=
add
(1, shl(1, _position))
right_ :=
or
(1, shl(1, _position))
}
}
/**
* @notice Get the parent position of `position`.
* @notice Get the parent position of `
_
position`.
* @param _position The position to get the parent position of.
* @return parent_ The parent position of `position`.
*/
...
...
@@ -91,10 +102,11 @@ library LibPosition {
}
/**
* @notice Get the deepest, right most index relative to the `position`.
* @param _position The position to get the relative deepest, right most index of.
* @notice Get the deepest, right most gindex relative to the `position`. This is equivalent to
* calling `right` on a position until the maximum depth is reached.
* @param _position The position to get the relative deepest, right most gindex of.
* @param _maxDepth The maximum depth of the game.
* @return rightIndex_ The deepest, right most index relative to the `position`.
* @return rightIndex_ The deepest, right most
g
index relative to the `position`.
*/
function rightIndex(
Position _position,
...
...
@@ -102,34 +114,22 @@ library LibPosition {
) internal pure returns (Position rightIndex_) {
uint256 msb = depth(_position);
assembly {
switch eq(msb, _maxDepth)
case true {
rightIndex_ := _position
}
default {
let remaining := sub(_maxDepth, msb)
rightIndex_ := or(shl(remaining, _position), sub(shl(remaining, 1), 1))
}
}
}
/**
* @notice Get the attack position relative to `position`.
* @param _position The position to get the relative attack position of.
* @return attack_ The attack position relative to `position`.
*/
function attack(Position _position) internal pure returns (Position attack_) {
return left(_position);
}
/**
* @notice Get the defense position relative to `position`.
* @param _position The position to get the relative defense position of.
* @return defense_ The defense position relative to `position`.
* @notice Get the move position of `_position`, which is the left child of:
* 1. `_position + 1` if `_isAttack` is true.
* 1. `_position` if `_isAttack` is false.
* @param _position The position to get the relative attack/defense position of.
* @param _isAttack Whether or not the move is an attack move.
* @return move_ The move position relative to `position`.
*/
function
defend(Position _position) internal pure returns (Position defens
e_) {
function
move(Position _position, bool _isAttack) internal pure returns (Position mov
e_) {
assembly {
defense_ := shl(1, add(1, shl(1, shr(1, _position))
))
move_ := shl(1, or(iszero(_isAttack), _position
))
}
}
}
packages/contracts-bedrock/contracts/test/FaultDisputeGame.t.sol
View file @
72c6fb0a
...
...
@@ -157,7 +157,7 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init {
/**
* @dev Tests that an attempt to defend the root claim reverts with the `CannotDefendRootClaim` error.
*/
function test_defendRoot_reverts() public {
function test_defendRoot_
invalidMove_
reverts() public {
vm.expectRevert(CannotDefendRootClaim.selector);
gameProxy.defend(0, Claim.wrap(bytes32(uint256(5))));
}
...
...
@@ -166,7 +166,7 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init {
* @dev Tests that an attempt to move against a claim that does not exist reverts with the
* `ParentDoesNotExist` error.
*/
function test_move
AgainstNone
xistentParent_reverts() public {
function test_move
_nonE
xistentParent_reverts() public {
Claim claim = Claim.wrap(bytes32(uint256(5)));
// Expect an out of bounds revert for an attack
...
...
@@ -182,7 +182,7 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init {
* @dev Tests that an attempt to move at the maximum game depth reverts with the
* `GameDepthExceeded` error.
*/
function test_gameDepthExceeded_reverts() public {
function test_
move_
gameDepthExceeded_reverts() public {
Claim claim = Claim.wrap(bytes32(uint256(5)));
uint256 maxDepth = gameProxy.MAX_GAME_DEPTH();
...
...
@@ -201,7 +201,7 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init {
* @dev Tests that a move made after the clock time has exceeded reverts with the
* `ClockTimeExceeded` error.
*/
function test_clockTimeExceeded_reverts() public {
function test_
move_
clockTimeExceeded_reverts() public {
// Warp ahead past the clock time for the first move (3 1/2 days)
vm.warp(block.timestamp + 3 days + 12 hours + 1);
vm.expectRevert(ClockTimeExceeded.selector);
...
...
@@ -212,7 +212,7 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init {
* @dev Tests that an identical claim cannot be made twice. The duplicate claim attempt should
* revert with the `ClaimAlreadyExists` error.
*/
function test_duplicateClaim_reverts() public {
function test_
move_
duplicateClaim_reverts() public {
Claim claim = Claim.wrap(bytes32(uint256(5)));
// Make the first move. This should succeed.
...
...
@@ -250,7 +250,7 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init {
assertEq(parentIndex, 0);
assertEq(countered, false);
assertEq(Claim.unwrap(claim), Claim.unwrap(counter));
assertEq(Position.unwrap(position), Position.unwrap(Position.wrap(1).
attack(
)));
assertEq(Position.unwrap(position), Position.unwrap(Position.wrap(1).
move(true
)));
assertEq(
Clock.unwrap(clock),
Clock.unwrap(LibClock.wrap(Duration.wrap(5), Timestamp.wrap(uint64(block.timestamp))))
...
...
@@ -384,7 +384,7 @@ contract GamePlayer {
if (grandparentIndex == type(uint32).max) {
// If the parent claim is the root claim, begin by attacking.
movePos = parentPos.
attack(
);
movePos = parentPos.
move(true
);
// Flag the move as an attack.
isAttack = true;
} else {
...
...
@@ -402,10 +402,10 @@ contract GamePlayer {
if (Claim.unwrap(ourParentClaim) != Claim.unwrap(parentClaim)) {
// Attack parent.
movePos = parentPos.
attack(
);
movePos = parentPos.
move(true
);
// If we also disagree with the grandparent, attack it as well.
if (Claim.unwrap(ourGrandparentClaim) != Claim.unwrap(grandparentClaim)) {
movePos2 = grandparentPos.
attack(
);
movePos2 = grandparentPos.
move(true
);
}
// Flag the move as an attack.
...
...
@@ -414,7 +414,7 @@ contract GamePlayer {
Claim.unwrap(ourParentClaim) == Claim.unwrap(parentClaim) &&
Claim.unwrap(ourGrandparentClaim) == Claim.unwrap(grandparentClaim)
) {
movePos = parentPos.
defend(
);
movePos = parentPos.
move(false
);
}
}
...
...
@@ -474,7 +474,7 @@ contract GamePlayer {
// If we have a second move position, attack the grandparent.
if (Position.unwrap(movePos2) != 0) {
(, , , Position grandparentPos, ) = gameProxy.claimData(grandparentIndex);
Claim ourGrandparentClaim = claimAt(grandparentPos.
attack(
));
Claim ourGrandparentClaim = claimAt(grandparentPos.
move(true
));
gameProxy.attack(grandparentIndex, ourGrandparentClaim);
counterParty.play(claimDataLen() - 1);
...
...
packages/contracts-bedrock/contracts/test/LibPosition.t.sol
View file @
72c6fb0a
...
...
@@ -28,7 +28,7 @@ contract LibPosition_Test is Test {
/**
* @notice Tests that the `depth` function correctly shifts out the `depth` from a packed `Position` type.
*/
function testFuzz_depth_correctness(uint8 _depth, uint64 _indexAtDepth) public {
function testFuzz_depth_correctness
_suceeds
(uint8 _depth, uint64 _indexAtDepth) public {
_depth = uint8(bound(_depth, 0, MAX_DEPTH));
_indexAtDepth = boundIndexAtDepth(_depth, _indexAtDepth);
Position position = LibPosition.wrap(_depth, _indexAtDepth);
...
...
@@ -38,7 +38,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(uint8 _depth, uint64 _indexAtDepth) public {
function testFuzz_indexAtDepth_correctness
_suceeds
(uint8 _depth, uint64 _indexAtDepth) public {
_depth = uint8(bound(_depth, 0, MAX_DEPTH));
_indexAtDepth = boundIndexAtDepth(_depth, _indexAtDepth);
Position position = LibPosition.wrap(_depth, _indexAtDepth);
...
...
@@ -48,7 +48,7 @@ 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, uint64 _indexAtDepth) public {
function testFuzz_left_correctness
_suceeds
(uint8 _depth, uint64 _indexAtDepth) public {
_depth = uint8(bound(_depth, 0, MAX_DEPTH));
_indexAtDepth = boundIndexAtDepth(_depth, _indexAtDepth);
...
...
@@ -62,7 +62,7 @@ contract LibPosition_Test is Test {
/**
* @notice Tests that the `right` function correctly computes the position of the right child.
*/
function testFuzz_right_correctness(uint8 _depth, uint64 _indexAtDepth) public {
function testFuzz_right_correctness
_suceeds
(uint8 _depth, uint64 _indexAtDepth) public {
// Depth bound: [0, 63]
_depth = uint8(bound(_depth, 0, MAX_DEPTH));
_indexAtDepth = boundIndexAtDepth(_depth, _indexAtDepth);
...
...
@@ -77,7 +77,7 @@ contract LibPosition_Test is Test {
/**
* @notice Tests that the `parent` function correctly computes the position of the parent.
*/
function testFuzz_parent_correctness(uint8 _depth, uint64 _indexAtDepth) public {
function testFuzz_parent_correctness
_suceeds
(uint8 _depth, uint64 _indexAtDepth) public {
_depth = uint8(bound(_depth, 1, MAX_DEPTH));
_indexAtDepth = boundIndexAtDepth(_depth, _indexAtDepth);
...
...
@@ -92,7 +92,7 @@ contract LibPosition_Test is Test {
* @notice Tests that the `rightIndex` function correctly computes the deepest, right most index relative
* to a given position.
*/
function testFuzz_rightIndex_correctness(
function testFuzz_rightIndex_correctness
_suceeds
(
uint64 _maxDepth,
uint8 _depth,
uint64 _indexAtDepth
...
...
@@ -120,13 +120,13 @@ 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, uint64 _indexAtDepth) public {
function testFuzz_attack_correctness
_suceeds
(uint8 _depth, uint64 _indexAtDepth) public {
// Depth bound: [0, 63]
_depth = uint8(bound(_depth, 0, MAX_DEPTH));
_indexAtDepth = boundIndexAtDepth(_depth, _indexAtDepth);
Position position = LibPosition.wrap(_depth, _indexAtDepth);
Position attack = position.
attack(
);
Position attack = position.
move(true
);
assertEq(attack.depth(), _depth + 1);
assertEq(attack.indexAtDepth(), _indexAtDepth * 2);
...
...
@@ -138,15 +138,271 @@ 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, uint64 _indexAtDepth) public {
function testFuzz_defend_correctness
_suceeds
(uint8 _depth, uint64 _indexAtDepth) public {
// Depth bound: [1, 63]
_depth = uint8(bound(_depth, 1, MAX_DEPTH));
_indexAtDepth = boundIndexAtDepth(_depth, _indexAtDepth);
Position position = LibPosition.wrap(_depth, _indexAtDepth);
Position defend = position.
defend(
);
Position defend = position.
move(false
);
assertEq(defend.depth(), _depth + 1);
assertEq(defend.indexAtDepth(), ((_indexAtDepth / 2) * 2 + 1) * 2);
}
/**
* @notice A static unit test for the correctness of all gindicies, (depth, index) combos,
* and the trace index in a tree of max depth = 4.
*/
function test_pos_correctness_succeeds() public {
uint256 maxDepth = 4;
Position p = LibPosition.wrap(0, 0);
assertEq(Position.unwrap(p), 1); // gindex = 1
assertEq(p.depth(), 0); // depth = 0
assertEq(p.indexAtDepth(), 0); // indexAtDepth = 0
Position r = p.rightIndex(maxDepth);
assertEq(Position.unwrap(r), 31); // right gindex = 31
assertEq(r.indexAtDepth(), 15); // trace index = 15
p = LibPosition.wrap(1, 0);
assertEq(Position.unwrap(p), 2); // gindex = 2
assertEq(p.depth(), 1); // depth = 1
assertEq(p.indexAtDepth(), 0); // indexAtDepth = 0
r = p.rightIndex(maxDepth);
assertEq(Position.unwrap(r), 23); // right gindex = 23
assertEq(r.indexAtDepth(), 7); // trace index = 7
p = LibPosition.wrap(1, 1);
assertEq(Position.unwrap(p), 3); // gindex = 3
assertEq(p.depth(), 1); // depth = 1
assertEq(p.indexAtDepth(), 1); // indexAtDepth = 1
r = p.rightIndex(maxDepth);
assertEq(Position.unwrap(r), 31); // right gindex = 31
assertEq(r.indexAtDepth(), 15); // trace index = 15
p = LibPosition.wrap(2, 0);
assertEq(Position.unwrap(p), 4); // gindex = 4
assertEq(p.depth(), 2); // depth = 2
assertEq(p.indexAtDepth(), 0); // indexAtDepth = 0
r = p.rightIndex(maxDepth);
assertEq(Position.unwrap(r), 19); // right gindex = 19
assertEq(r.indexAtDepth(), 3); // trace index = 3
p = LibPosition.wrap(2, 1);
assertEq(Position.unwrap(p), 5); // gindex = 5
assertEq(p.depth(), 2); // depth = 2
assertEq(p.indexAtDepth(), 1); // indexAtDepth = 1
r = p.rightIndex(maxDepth);
assertEq(Position.unwrap(r), 23); // right gindex = 23
assertEq(r.indexAtDepth(), 7); // trace index = 7
p = LibPosition.wrap(2, 2);
assertEq(Position.unwrap(p), 6); // gindex = 6
assertEq(p.depth(), 2); // depth = 2
assertEq(p.indexAtDepth(), 2); // indexAtDepth = 2
r = p.rightIndex(maxDepth);
assertEq(Position.unwrap(r), 27); // right gindex = 27
assertEq(r.indexAtDepth(), 11); // trace index = 11
p = LibPosition.wrap(2, 3);
assertEq(Position.unwrap(p), 7); // gindex = 7
assertEq(p.depth(), 2); // depth = 2
assertEq(p.indexAtDepth(), 3); // indexAtDepth = 3
r = p.rightIndex(maxDepth);
assertEq(Position.unwrap(r), 31); // right gindex = 31
assertEq(r.indexAtDepth(), 15); // trace index = 15
p = LibPosition.wrap(3, 0);
assertEq(Position.unwrap(p), 8); // gindex = 8
assertEq(p.depth(), 3); // depth = 3
assertEq(p.indexAtDepth(), 0); // indexAtDepth = 0
r = p.rightIndex(maxDepth);
assertEq(Position.unwrap(r), 17); // right gindex = 17
assertEq(r.indexAtDepth(), 1); // trace index = 1
p = LibPosition.wrap(3, 1);
assertEq(Position.unwrap(p), 9); // gindex = 9
assertEq(p.depth(), 3); // depth = 3
assertEq(p.indexAtDepth(), 1); // indexAtDepth = 1
r = p.rightIndex(maxDepth);
assertEq(Position.unwrap(r), 19); // right gindex = 19
assertEq(r.indexAtDepth(), 3); // trace index = 3
p = LibPosition.wrap(3, 2);
assertEq(Position.unwrap(p), 10); // gindex = 10
assertEq(p.depth(), 3); // depth = 3
assertEq(p.indexAtDepth(), 2); // indexAtDepth = 2
r = p.rightIndex(maxDepth);
assertEq(Position.unwrap(r), 21); // right gindex = 21
assertEq(r.indexAtDepth(), 5); // trace index = 5
p = LibPosition.wrap(3, 3);
assertEq(Position.unwrap(p), 11); // gindex = 11
assertEq(p.depth(), 3); // depth = 3
assertEq(p.indexAtDepth(), 3); // indexAtDepth = 3
r = p.rightIndex(maxDepth);
assertEq(Position.unwrap(r), 23); // right gindex = 23
assertEq(r.indexAtDepth(), 7); // trace index = 7
p = LibPosition.wrap(3, 4);
assertEq(Position.unwrap(p), 12); // gindex = 12
assertEq(p.depth(), 3); // depth = 3
assertEq(p.indexAtDepth(), 4); // indexAtDepth = 4
r = p.rightIndex(maxDepth);
assertEq(Position.unwrap(r), 25); // right gindex = 25
assertEq(r.indexAtDepth(), 9); // trace index = 9
p = LibPosition.wrap(3, 5);
assertEq(Position.unwrap(p), 13); // gindex = 13
assertEq(p.depth(), 3); // depth = 3
assertEq(p.indexAtDepth(), 5); // indexAtDepth = 5
r = p.rightIndex(maxDepth);
assertEq(Position.unwrap(r), 27); // right gindex = 27
assertEq(r.indexAtDepth(), 11); // trace index = 11
p = LibPosition.wrap(3, 6);
assertEq(Position.unwrap(p), 14); // gindex = 14
assertEq(p.depth(), 3); // depth = 3
assertEq(p.indexAtDepth(), 6); // indexAtDepth = 6
r = p.rightIndex(maxDepth);
assertEq(Position.unwrap(r), 29); // right gindex = 29
assertEq(r.indexAtDepth(), 13); // trace index = 13
p = LibPosition.wrap(3, 7);
assertEq(Position.unwrap(p), 15); // gindex = 15
assertEq(p.depth(), 3); // depth = 3
assertEq(p.indexAtDepth(), 7); // indexAtDepth = 7
r = p.rightIndex(maxDepth);
assertEq(Position.unwrap(r), 31); // right gindex = 31
assertEq(r.indexAtDepth(), 15); // trace index = 15
p = LibPosition.wrap(4, 0);
assertEq(Position.unwrap(p), 16); // gindex = 16
assertEq(p.depth(), 4); // depth = 4
assertEq(p.indexAtDepth(), 0); // indexAtDepth = 0
r = p.rightIndex(maxDepth);
assertEq(Position.unwrap(r), 16); // right gindex = 16
assertEq(r.indexAtDepth(), 0); // trace index = 0
p = LibPosition.wrap(4, 1);
assertEq(Position.unwrap(p), 17); // gindex = 17
assertEq(p.depth(), 4); // depth = 4
assertEq(p.indexAtDepth(), 1); // indexAtDepth = 1
r = p.rightIndex(maxDepth);
assertEq(Position.unwrap(r), 17); // right gindex = 17
assertEq(r.indexAtDepth(), 1); // trace index = 1
p = LibPosition.wrap(4, 2);
assertEq(Position.unwrap(p), 18); // gindex = 18
assertEq(p.depth(), 4); // depth = 4
assertEq(p.indexAtDepth(), 2); // indexAtDepth = 2
r = p.rightIndex(maxDepth);
assertEq(Position.unwrap(r), 18); // right gindex = 18
assertEq(r.indexAtDepth(), 2); // trace index = 2
p = LibPosition.wrap(4, 3);
assertEq(Position.unwrap(p), 19); // gindex = 19
assertEq(p.depth(), 4); // depth = 4
assertEq(p.indexAtDepth(), 3); // indexAtDepth = 3
r = p.rightIndex(maxDepth);
assertEq(Position.unwrap(r), 19); // right gindex = 19
assertEq(r.indexAtDepth(), 3); // trace index = 3
p = LibPosition.wrap(4, 4);
assertEq(Position.unwrap(p), 20); // gindex = 20
assertEq(p.depth(), 4); // depth = 4
assertEq(p.indexAtDepth(), 4); // indexAtDepth = 4
r = p.rightIndex(maxDepth);
assertEq(Position.unwrap(r), 20); // right gindex = 20
assertEq(r.indexAtDepth(), 4); // trace index = 4
p = LibPosition.wrap(4, 5);
assertEq(Position.unwrap(p), 21); // gindex = 21
assertEq(p.depth(), 4); // depth = 4
assertEq(p.indexAtDepth(), 5); // indexAtDepth = 5
r = p.rightIndex(maxDepth);
assertEq(Position.unwrap(r), 21); // right gindex = 21
assertEq(r.indexAtDepth(), 5); // trace index = 5
p = LibPosition.wrap(4, 6);
assertEq(Position.unwrap(p), 22); // gindex = 22
assertEq(p.depth(), 4); // depth = 4
assertEq(p.indexAtDepth(), 6); // indexAtDepth = 6
r = p.rightIndex(maxDepth);
assertEq(Position.unwrap(r), 22); // right gindex = 22
assertEq(r.indexAtDepth(), 6); // trace index = 6
p = LibPosition.wrap(4, 7);
assertEq(Position.unwrap(p), 23); // gindex = 23
assertEq(p.depth(), 4); // depth = 4
assertEq(p.indexAtDepth(), 7); // indexAtDepth = 7
r = p.rightIndex(maxDepth);
assertEq(Position.unwrap(r), 23); // right gindex = 23
assertEq(r.indexAtDepth(), 7); // trace index = 7
p = LibPosition.wrap(4, 8);
assertEq(Position.unwrap(p), 24); // gindex = 24
assertEq(p.depth(), 4); // depth = 4
assertEq(p.indexAtDepth(), 8); // indexAtDepth = 8
r = p.rightIndex(maxDepth);
assertEq(Position.unwrap(r), 24); // right gindex = 24
assertEq(r.indexAtDepth(), 8); // trace index = 8
p = LibPosition.wrap(4, 9);
assertEq(Position.unwrap(p), 25); // gindex = 25
assertEq(p.depth(), 4); // depth = 4
assertEq(p.indexAtDepth(), 9); // indexAtDepth = 9
r = p.rightIndex(maxDepth);
assertEq(Position.unwrap(r), 25); // right gindex = 25
assertEq(r.indexAtDepth(), 9); // trace index = 9
p = LibPosition.wrap(4, 10);
assertEq(Position.unwrap(p), 26); // gindex = 26
assertEq(p.depth(), 4); // depth = 4
assertEq(p.indexAtDepth(), 10); // indexAtDepth = 10
r = p.rightIndex(maxDepth);
assertEq(Position.unwrap(r), 26); // right gindex = 26
assertEq(r.indexAtDepth(), 10); // trace index = 10
p = LibPosition.wrap(4, 11);
assertEq(Position.unwrap(p), 27); // gindex = 27
assertEq(p.depth(), 4); // depth = 4
assertEq(p.indexAtDepth(), 11); // indexAtDepth = 11
r = p.rightIndex(maxDepth);
assertEq(Position.unwrap(r), 27); // right gindex = 27
assertEq(r.indexAtDepth(), 11); // trace index = 11
p = LibPosition.wrap(4, 12);
assertEq(Position.unwrap(p), 28); // gindex = 28
assertEq(p.depth(), 4); // depth = 4
assertEq(p.indexAtDepth(), 12); // indexAtDepth = 12
r = p.rightIndex(maxDepth);
assertEq(Position.unwrap(r), 28); // right gindex = 28
assertEq(r.indexAtDepth(), 12); // trace index = 12
p = LibPosition.wrap(4, 13);
assertEq(Position.unwrap(p), 29); // gindex = 29
assertEq(p.depth(), 4); // depth = 4
assertEq(p.indexAtDepth(), 13); // indexAtDepth = 13
r = p.rightIndex(maxDepth);
assertEq(Position.unwrap(r), 29); // right gindex = 29
assertEq(r.indexAtDepth(), 13); // trace index = 13
p = LibPosition.wrap(4, 14);
assertEq(Position.unwrap(p), 30); // gindex = 30
assertEq(p.depth(), 4); // depth = 4
assertEq(p.indexAtDepth(), 14); // indexAtDepth = 14
r = p.rightIndex(maxDepth);
assertEq(Position.unwrap(r), 30); // right gindex = 30
assertEq(r.indexAtDepth(), 14); // trace index = 14
p = LibPosition.wrap(4, 15);
assertEq(Position.unwrap(p), 31); // gindex = 31
assertEq(p.depth(), 4); // depth = 4
assertEq(p.indexAtDepth(), 15); // indexAtDepth = 15
r = p.rightIndex(maxDepth);
assertEq(Position.unwrap(r), 31); // right gindex = 31
assertEq(r.indexAtDepth(), 15); // trace index = 15
}
}
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