Skip to content

Conversation

@JustXxx
Copy link

@JustXxx JustXxx commented May 18, 2024

No description provided.

@JustXxx JustXxx requested review from qizhou, qzhodl and zhiqiangxu May 18, 2024 15:26
// state's depth in relation to the parent, we don't need another
// branch because (n - n) % 2 == 0.
bool validStep = VM.step(_stateData, _proof, uuid.raw()) == postState.claim.raw();
bool parentPostAgree = (parentPos.depth() - postState.position.depth()) % 2 == 0;
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It will be great if we can update the comment accordingly.

{
// Grab the trace ancestor's expected position.
Position traceAncestorPos = _global ? _pos.traceAncestor() : _pos.traceAncestorBounded(SPLIT_DEPTH);
Position traceAncestorPos = _global ? _pos.traceAncestorBounded(nBits - 1) : _pos.traceAncestorBounded(SPLIT_DEPTH);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not sure _pos.traceAncestorBounded(nBits - 1) is correct for both nBits == 1 and nBits > 1 cases.

For example, traceAncestor(3) = 1, while traceAncestorBounded(3, 0) = 3

Comment on lines 954 to 967
function traceAncestorV2(Position _position) public view returns (Position ancestor_) {
if (_position.depth() < nBits) {
revert ClaimAboveSplit();
}
ancestor_ = _position.traceAncestor();
// Position 1 is not the value submitted by the Actors.
if (1 == ancestor_.raw()) {
return ancestor_;
}
// The depth of the ancestor must not be less than the depth of the first attack position.
for (uint64 start = ancestor_.depth(); start < nBits; start++) {
ancestor_ = Position.wrap(ancestor_.raw() * 2 + 1);
}
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess the code should be

Suggested change
function traceAncestorV2(Position _position) public view returns (Position ancestor_) {
if (_position.depth() < nBits) {
revert ClaimAboveSplit();
}
ancestor_ = _position.traceAncestor();
// Position 1 is not the value submitted by the Actors.
if (1 == ancestor_.raw()) {
return ancestor_;
}
// The depth of the ancestor must not be less than the depth of the first attack position.
for (uint64 start = ancestor_.depth(); start < nBits; start++) {
ancestor_ = Position.wrap(ancestor_.raw() * 2 + 1);
}
}
function traceAncestorV2(Position _position) public view returns (Position ancestor_) {
if (_position.depth() % nBits != 0) {
revert SomeError();
}
return _position.traceAncestor().roundUp(nBits);
}

For example, when nBits = 2 and position = 17, it should return 17 rather than 8.

// Grab the trace ancestor's expected position.
Position traceAncestorPos = _global ? _pos.traceAncestor() : _pos.traceAncestorBounded(SPLIT_DEPTH);
Position traceAncestorPos = _global
? traceAncestorV2(_pos) : _pos.traceAncestorBounded(findFirstValueDepth(SPLIT_DEPTH));
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we assume SPLIT_DEPTH % nBits == 0, I believe code can be

Suggested change
? traceAncestorV2(_pos) : _pos.traceAncestorBounded(findFirstValueDepth(SPLIT_DEPTH));
? traceAncestor(_pos).roundUp(nBits): _pos.traceAncestorBounded(SPLIT_DEPTH + nBits - 1).roundUp(nBits);

where

  function roundUp(Position _position, uint256 _nBits) internal pure returns (Position _roundUp) {
        _roundUp = _position;
        for (uint64 start = _roundUp.depth(); start % _nBits != 0; start++) {
            _roundUp = _roundUp.right();
        }
        return _roundUp;
    }

or

  function roundUp(Position _position, uint256 _nBits) internal pure returns (Position _roundUp) {
        uint256 targetDepth = _position.depth();
        if (targetDepth % _nBits != 0) {
            targetDepth = targetDepth + _nBits - targetDepth % nBits;
        }
        return _position.rightIndex(targetDepth);
    }

Comment on lines 955 to 969
function _traceAncestorV2(Position _position, uint256 _intervalDepth)
internal
pure
returns (Position ancestor_)
{
if (_position.depth() % _intervalDepth != 0 || _position.depth() < _intervalDepth) {
revert InvalidClaim();
}
ancestor_ = _position.traceAncestor();
// Position 1 is not the value submitted by the Actors.
if (1 == ancestor_.raw()) {
return ancestor_;
}
return _firstValidPosition(ancestor_, _intervalDepth);
}

Check failure

Code scanning / Slither

Weak PRNG

FaultDisputeGame._traceAncestorV2(Position,uint256) (src/dispute/FaultDisputeGame2.sol#955-969) uses a weak PRNG: "_position.depth() % _intervalDepth != 0 || _position.depth() < _intervalDepth (src/dispute/FaultDisputeGame2.sol#960)"
pure
returns (Position ancestor_)
{
if (_position.depth() % _intervalDepth != 0 || _position.depth() < _intervalDepth) {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think _traceAncestorV2(pos, 1) should behave the same as _traceAncestor, which accept $1$ as input.

revert InvalidClaim();
}
ancestor_ = _position.traceAncestor();
// Position 1 is not the value submitted by the Actors.
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not sure of the comment's meaning. In addition, I do not think we need a special check for 1 == ancestor_.raw()

/// @param _position Current location
/// @param _intervalDepth The depth of the interval with each submission.
/// @return first_ First valid location
function _firstValidPosition(Position _position, uint256 _intervalDepth)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

first may be confusing since it can be vertical (depth) or horizontal.

I think we can use validRightIndex or firstValidRightIndex.

Comment on lines +971 to +980
function _firstValidRightIndex(Position _position, uint256 _intervalDepth)
internal
pure
returns (Position first_)
{
first_ = _position;
for (uint64 start = first_.depth(); start % _intervalDepth != 0; start++) {
first_ = first_.right();
}
}

Check failure

Code scanning / Slither

Weak PRNG

FaultDisputeGame._firstValidRightIndex(Position,uint256) (src/dispute/FaultDisputeGame2.sol#971-980) uses a weak PRNG: "start % _intervalDepth != 0 (src/dispute/FaultDisputeGame2.sol#977)"
/// @param _position Current location
/// @param _intervalDepth The depth of the interval with each submission.
/// @return first_ First valid location
function _firstValidRightIndex(Position _position, uint256 _intervalDepth)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This may be moved to LibPosition.sol

@JustXxx
Copy link
Author

JustXxx commented Jul 20, 2024

fix by #35

@JustXxx JustXxx closed this Jul 20, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants