Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Solidity contract that accepts unverified substrate headers #65

Merged
merged 55 commits into from
Apr 29, 2020

Conversation

svyatonik
Copy link
Contributor

part of #50

This PR introduces:

  1. ethereum-contract-builtin crate, which will be used by bridge contract to import headers and verify finality proofs. Right now it has fn parse_substrate_header(), which is (almost) completed and fn verify_substrate_finality_proof() which is unimplemented. This combination allows contract to import Substrate headers, but not to import finality proofs;
  2. solidity contract that is able to import unverified Substrate headers and (in theory) import and verify finality proofs;
  3. sub-to-eth subcommand for the relay to be able to test that headers sync. The pipeline is almost the same as in eth-to-sub, but we have no extra data to be submitted along with header (like transactions receipts in eth-to-sub). Also just realized that there are some parts of future AsyncExtra data sync (which is finality proof in our case) - can remove on demand, just wanted to make separate PRs for headers import and finality proof import;
  4. eth-deploy-contract subcommand for the relay which deploys bridge contract on eth-like chain. We may throw it later, or make a separate binary, but right now I find it much more convenient to have it as a subcommand in relay.

Some details:

  1. in the first version of contract, it has been able to import only finalized headers - i.e. it had function importHeaders(bytes[] calldata rawHeaders, bytes calldata rawFinalityProof) instead of two functions (function importHeader() and function importFinalityProof()) now. But it might be impossible to fit this data in single transaction in some cases (like when GRANDA validators were unable to finalize headers for some long time);
  2. there is no pruning in bridge contract now, mostly for simplicity - we may add support later. But we need to take Prune old headers with separate transaction #62 into account;
  3. relay code is mostly the same, though there are some new RPC calls for both Substrate and Ethereum nodes. So most new lines are utility lines describing sub-to-eth sync, code reorgs and the contract itself. I was thinking of introducing tests for the contract, but then realized that I won't be able to do that without mocking builtins. And I do not know any way to mock builtins. So the contract comes without any unit tests - please advice if you know any way to solve it.

Copy link
Contributor

@tomusdrw tomusdrw left a comment

Choose a reason for hiding this comment

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

Looks good overall, I'd like to see contract metadata file fixed in this PR and the small grumbles, but major things (like RPC caling refactor, or constant extraction) can be done in separate PRs. I will turn them into issues.

}

/// Initializes bridge contract.
/// @param rawInitialHeader Raw finalized header that will be ancestor of all importing headers.
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
/// @param rawInitialHeader Raw finalized header that will be ancestor of all importing headers.
/// @param rawInitialHeader Raw finalized header that will be ancestor of all imported headers.

) public {
// check that header that we're going to finalize is already imported
require(
headerByHash[finalityTargetHash].number == finalityTargetNumber,
Copy link
Contributor

Choose a reason for hiding this comment

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

It think we should make sure that finalityTargetNumber is not 0 too:

Suggested change
headerByHash[finalityTargetHash].number == finalityTargetNumber,
headerByHash[finalityTargetHash].number == finalityTargetNumber && finalityTargetNumber != 0,

Copy link
Contributor Author

Choose a reason for hiding this comment

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

[SOLIDITY] I'm not against that (will consider that when preparing final version of the contract), but I see nothing criminal in re-finalizing finalized block (genesis in this case) - it just should be a noop. Do you have any other concerns to mention?

Copy link
Contributor

Choose a reason for hiding this comment

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

Since 0 is used for initialized storage as well, I'd prefer to keep it on the safe side here. i.e. with finalityTargetNumber ==0 this check would pass with arbitrarty finalityTargetHash (i.e. non-existent).
So nothing very specific for now, but just my internal warning side lightning up :)

require(
!headerByHash[header.hash].isKnown,
"Header is already known"
);
Copy link
Contributor

Choose a reason for hiding this comment

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

Let's add an extra check that we are not importing a header with hash=0 or number=0. We can optimize this later if it turns out not needed.
Just to be on the safe side :)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

[SOLIDITY] This is checked by the parentHeader.isKnown && parentHeader.number == header.number - 1, later. So unless we'll have 2^32 headers (which will break contract assumptions anyway), we won't allow to import such headers.

Solc version: 0.6.6+commit.6c089d02
Source hash (keccak256): 0xdc46aff04e37129265223e507d17f1407a70cb1ecea3230e1eaa77a17586724d
Source gist: https://gist.github.com/svyatonik/876b388f9507a8de242cb2db9547c4f0
Compiler flags used (command to produce the file): `docker run -i ethereum/solc:0.6.6 --optimize --bin - < substrate-bridge.sol`
Copy link
Contributor

Choose a reason for hiding this comment

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

🙇‍♂️

) public {
// check that header that we're going to finalize is already imported
require(
headerByHash[finalityTargetHash].number == finalityTargetNumber,
Copy link
Contributor

Choose a reason for hiding this comment

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

Since 0 is used for initialized storage as well, I'd prefer to keep it on the safe side here. i.e. with finalityTargetNumber ==0 this check would pass with arbitrarty finalityTargetHash (i.e. non-existent).
So nothing very specific for now, but just my internal warning side lightning up :)

Copy link
Contributor

@tomusdrw tomusdrw left a comment

Choose a reason for hiding this comment

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

Looks good for me. There are couple of rename suggestions by @HCastano - I don't really have a strong opinion, cause the plural sounds ok to me, but I'm not a native speaker.

@@ -0,0 +1,5 @@
Last Change Date: 2020-04-28
Copy link
Contributor

Choose a reason for hiding this comment

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

Is this date necessary? Could we not get this from the commit info?

Copy link
Contributor

Choose a reason for hiding this comment

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

Commits sometimes get lost (when you move to a new repo) or we might move stuff around. I'd prefer to keep it explicitly.

@HCastano
Copy link
Contributor

Looks good for me. There are couple of rename suggestions by @HCastano - I don't really have a strong opinion, cause the plural sounds ok to me, but I'm not a native speaker.

If the structs were some sort of collection I'd be okay with the plurals. Since they're not the naming is a bit awkward. While I would prefer to see them changed, I also don't have a strong enough opinion that I'm going to block this over the naming, lol

ethabi = "12.0"
ethabi-contract = "11.0"
ethabi-derive = "11.0"
ethereum-tx-sign = { git = "https://github.com/svyatonik/ethereum-tx-sign.git", branch = "up-ethereum-types" }
Copy link
Contributor Author

Choose a reason for hiding this comment

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

The biggest change of latest merge-with-master - PR is already opened in original repo, but let's refer to my branch for now

@svyatonik svyatonik merged commit 9993873 into master Apr 29, 2020
@HCastano HCastano deleted the solidity-contract branch April 29, 2020 15:42
svyatonik pushed a commit that referenced this pull request Jul 17, 2023
Otherwise the first positional argument is just swallowed

Fixes #62

Forked at: cd1eb37
Parent branch: origin/master
serban300 pushed a commit to serban300/parity-bridges-common that referenced this pull request Mar 27, 2024
…ch#65)

* solidity contract

* continue

* upd

* cargo update

* fixes

* ehtereum_headers -> headers

* extracted some common stuff

* ethereum_sync.rs -> sync.rs

* make sync generic

* continue extracting

* continue

* add eth-contract argument

* continue

* some fixes

* contract v2

* continue

* more fixes

* more fixes

* deal with duplicated params

* removed multiple call_rpc variants

* bail_on_error!()

* fn submit_ethereum_transaction

* more fixes

* cargo fmt --all

* fix

* bail_on_arg_error!()

* fix

* fix

* remove async_extra stuff

* substrate-bridge.json -> substrate-bridge-abi.json

* get rid of substrate transactions hashes

* get rid of ethereum transactions hashes

* extracted contract bytecode to separate file

* cargo fmt --all

* avoid duplicate import in contracts

* removed Default::default()

* swapped configurations for sub2eth && eth2sub

* fix compilation

* do not double gas limit when submitting Substrate headers

* cargo fmt --all

* solidity contract removed

* consts

* extracted solc compilation details to separate file

* removed (obsolete in future Vec<u8> justification)

* fixed cli option description

* fix typos

* fix grumble

* extracted constants

* log decoded header

* cargo fmt --all

* comment
serban300 pushed a commit to serban300/parity-bridges-common that referenced this pull request Apr 8, 2024
…ch#65)

* solidity contract

* continue

* upd

* cargo update

* fixes

* ehtereum_headers -> headers

* extracted some common stuff

* ethereum_sync.rs -> sync.rs

* make sync generic

* continue extracting

* continue

* add eth-contract argument

* continue

* some fixes

* contract v2

* continue

* more fixes

* more fixes

* deal with duplicated params

* removed multiple call_rpc variants

* bail_on_error!()

* fn submit_ethereum_transaction

* more fixes

* cargo fmt --all

* fix

* bail_on_arg_error!()

* fix

* fix

* remove async_extra stuff

* substrate-bridge.json -> substrate-bridge-abi.json

* get rid of substrate transactions hashes

* get rid of ethereum transactions hashes

* extracted contract bytecode to separate file

* cargo fmt --all

* avoid duplicate import in contracts

* removed Default::default()

* swapped configurations for sub2eth && eth2sub

* fix compilation

* do not double gas limit when submitting Substrate headers

* cargo fmt --all

* solidity contract removed

* consts

* extracted solc compilation details to separate file

* removed (obsolete in future Vec<u8> justification)

* fixed cli option description

* fix typos

* fix grumble

* extracted constants

* log decoded header

* cargo fmt --all

* comment
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.

3 participants