-
Notifications
You must be signed in to change notification settings - Fork 8
Change the state machine used for processing new blocks #20
Conversation
nearbridge/contracts/NearBridge.sol
Outdated
BlockInfo public backupHead; | ||
|
||
// The most recently added block. May still be in its challenge period, so should not be trusted. | ||
BlockInfo public untrustedHead; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great to make a difference between head and untrustedHead!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good, need bump version in package.json if we want to use this immediately. verify_near_headers test failed because it simply try to submit all blocks during a period, so refused by "not sufficiently new" check, either change test or remove some blocks for now
0bfa9af
to
6bd6a89
Compare
I fixed verify_near_headers, but it still won't pass cli tests because there is new constructor parameter. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This logic makes contract more complex by adding an additional public method. Instead we can make head
and backupHead
private and add an additional method getTrustedHead()
which returns either head
or backupHead
depending on whether validAfter
has passed.
I think that the logic is now less complex. There is Or I can just make Overall, this code needs a lot of refactoring, but for now I try not to change it too much. |
We could add
This will make header that passed challenge period not useful until the next header is submitted. Ideally, we want header to be useful as soon as it passes the challenge period. |
6bd6a89
to
b9e4819
Compare
That's not a good API design. "Trusted" should be the default (and indeed the only) option. Anyway, I changed the API to return the last block as soon as the challenge period is over. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good. There are some suggestions to add comments. We also need to add PR for rainbow-bridge-cli and rainbow-bridge-lib to make the tests pass. Sorry for the delay.
// Address of the account which submitted the last block. | ||
address lastSubmitter; | ||
// End of challenge period, or zero if there is no block to be challenged. | ||
uint lastValidAt; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please add a comment saying something like: "when it is zero untrustedHead
, untrustedHeadIsFromNextEpoch
, untrustedNextBlockProducers
should be considered to be not set".
b9e4819
to
8a889fa
Compare
@nearmax I addressed the comments and also fixed another bug, is everything OK now? Will make a PR for near-bridge-cli and -lib a bit later. I can't merge this PR because of CI. |
Created pull requests: Near-One/rainbow-bridge#348, near/rainbow-bridge-lib#14. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Approving, assuming https://github.com/near/rainbow-bridge-sol/pull/20/files?file-filters%5B%5D=.sol#diff-b55dd2aebd3038c032230f5c9710455dR212 is the only non-comment change since previous review.
} else { | ||
// The new block is from the next epoch. | ||
_checkBp(nearBlock, nextBlockProducers); | ||
revert("NearBridge: Epoch id of the block is not valid"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Was this the additional bug that you fixed? It is hard to see because of the forced push.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The bug that I fixed was that I added a check to checkBlockProducerSignatureInHead
that signatureIndex
is valid.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are you talking about signatureIndex < untrustedBlockProducers.bpsLength
check? Because it seems !untrustedApprovals[signatureIndex].none
check does not fix vulnerabilities.
1263476
to
baa0a8e
Compare
baa0a8e
to
f4ad769
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good!
@@ -15,6 +15,7 @@ do | |||
# Get contract name without extension and without directories. | |||
contract_name="${filename%.*}" | |||
node_modules/.bin/truffle-flattener "./contracts/${contract_name}.sol" > "dist/${contract_name}.full.sol" | |||
sed -i '/^\/\/ SPDX-License-Identifier:/d' "dist/${contract_name}.full.sol" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could we add a comment explaining what is this for?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This was because of NomicFoundation/truffle-flattener#55. Will add a comment.
nearbridge/contracts/NearBridge.sol
Outdated
@@ -75,26 +82,27 @@ contract NearBridge is INearBridge { | |||
bytes32 blockHash | |||
); | |||
|
|||
constructor(Ed25519 ed, uint256 _lockEthAmount, uint256 _lockDuration) public { | |||
constructor(Ed25519 ed, uint256 _lockEthAmount, uint256 _lockDuration, uint256 _replaceDuration) public { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This PR might be a good opportunity to make sure we follow Solidity style guide: https://solidity.readthedocs.io/en/v0.6.0/style-guide.html#avoiding-naming-collisions
balanceOf[msg.sender] = balanceOf[msg.sender].sub(lockEthAmount); | ||
msg.sender.transfer(lockEthAmount); | ||
} | ||
|
||
function challenge(address payable receiver, uint256 signatureIndex) public { | ||
require(block.timestamp < head.validAfter, "Lock period already passed"); | ||
function challenge(address payable receiver, uint256 signatureIndex) override public { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
AFAIU override
is only useful when contract inherits from another contract, not from an interface.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In Solidity 0.6, override
is mandatory when inheriting from an interface. Without it, it just won't compile.
res.currentHeight = head.height; | ||
res.nextTimestamp = untrustedHead.timestamp; | ||
res.nextValidAt = lastValidAt; | ||
res.numBlockProducers = |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is unclear why do we not return numBlockProducers
when there is an untrusted head.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We do return the number of block producers when there is an untrusted head. This number is used by the watchdog to determine the number of signatures to check.
nearbridge/contracts/NearBridge.sol
Outdated
function addLightClientBlock(bytes memory data) public payable { | ||
struct BridgeState { | ||
uint currentHeight; | ||
uint nextTimestamp; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could we please add comments explaining each field?
} else { | ||
// The new block is from the next epoch. | ||
_checkBp(nearBlock, nextBlockProducers); | ||
revert("NearBridge: Epoch id of the block is not valid"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are you talking about signatureIndex < untrustedBlockProducers.bpsLength
check? Because it seems !untrustedApprovals[signatureIndex].none
check does not fix vulnerabilities.
} | ||
|
||
// 6. If next_bps is not none, sha256(borsh(next_bps)) corresponds to the next_bp_hash in inner_lite. | ||
if (!nearBlock.next_bps.none) { | ||
// Check that the new block is signed by more than 2/3 of the validators. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The numbers in the comments were useful because they corresponded to the spec: https://nomicon.io/ChainSpec/LightClient.html
f4ad769
to
ea88dc6
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good
I have tested this change locally, so I am going to merge it and publish the package. |
Now a newly added block that is not yet trusted is stored in untrustedHead. After the challenge period is over, it can be moved to head. Fixes #13, #15.