-
Notifications
You must be signed in to change notification settings - Fork 1
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
Withdrawal intent 32byte pubkey #288
Conversation
burn bridge out amount add checks to funtional test
Codecov ReportAttention: Patch coverage is
@@ Coverage Diff @@
## master #288 +/- ##
==========================================
+ Coverage 58.73% 64.10% +5.37%
==========================================
Files 168 184 +16
Lines 16340 19425 +3085
==========================================
+ Hits 9597 12453 +2856
- Misses 6743 6972 +229
|
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.
Left some nits. Otherwise, looks good. :)
# 1 eth | ||
to_transfer = 1_000_000_000_000_000_000 | ||
# 10 rollup btc as wei | ||
to_transfer_wei = 10_000_000_000_000_000_000 |
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.
Should probably be added to constants.py
so it's easier to change this in the future if necessary.
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 should do that once we use this in other tests. Currently, this is the only test using these values.
@@ -8,19 +8,19 @@ use crate::primitives::WithdrawalIntentEvent; | |||
|
|||
// TODO: address? | |||
pub const BRIDGEOUT_ADDRESS: Address = address!("000000000000000000000000000000000b121d9e"); | |||
const MIN_WITHDRAWAL_WEI: u128 = 1_000_000_000_000_000_000u128; | |||
const WITHDRAWAL_WEI: u128 = 10 * (1e18 as u128); |
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.
Should be set from params, we shouldn't assume 10 BTC is hardcoded.
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 is in the reth binary and we haven't setup params for this yet. Will use constants for the time being.
}); | ||
} | ||
|
||
account.info.balance = new_balance; |
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.
Don't we have to write the account balance back to the state after making changes like this? Should have test(s) that checks to see if the account's balance actually decreases when they bridge out.
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 code is to burn the bridge out amount transferred to the bridge contract. The changes on the sender's side is done by evm itself.
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.
So shouldn't we just unconditionally set it to 0 then? Instead of doing the checked_sub
that we expect will always go to zero? We can add a sanity check to it to ensure that it's doing it right.
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.
updated
crates/reth/node/src/primitives.rs
Outdated
/// 32 bytes pubkey for withdrawal address in L1 | ||
bytes dest_pk, |
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.
bytes32
Also, I know this was implemented in the other ticket but is this really the best way to implement this? I thought StatefulPrecompile
would have been more correct.
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 originally planning to do this with StatefulPrecompile
, but ran into issues during implementation.
Specifically, StatefulPrecompile
does not provide access to modify evm state, nor to send event logs. So there was no way to communicate the precompile call info easily to the payload builder.
- Checking tx in the block manually in the builder would not work if the bridge out is called through a contract.
- It might be possible to pass a shared state from the builder to the stateful precompile somehow, but that implementation was getting quite ugly.
So I used the context precompile to send event logs and handled is similar to how the beacon chain deposits were already being handled.
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 might be possible to pass a shared state from the builder to the stateful precompile somehow, but that implementation was getting quite ugly.
Yeah I mean you'd have to use RefCell
probably which is kinda messy but I believe it would work.
Regardless I suppose this is a workable solution. It does require special filtering which feels like it violates layers but it's hard to get around that.
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.
Ahhh several review comments somehow didn't get picked up as review comments, I'm not sure if I screwed up or what. Make sure to read above for parts that didn't get included in this.
assert event_data.args.dest_pk.hex() == dest_pk | ||
|
||
final_block_no = web3.eth.block_number | ||
final_bridge_balance = web3.eth.get_balance(dest) |
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.
Precompiles can't have balances do they? At least we shouldn't be modelling it like that because that screws up the accounting. Unless it's hard to do anything about it, in which case nevermind I guess this works out.
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 precompile balance will always be zero as the value transferred to it is burned by the precompile.
There is an assertion below this that the final bridge balance should be zero.
Also bytes not bits. |
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 understand the strategy with this now. I want to make sure that we're totally sure we're doing this in a sensible way so some of these comments might be unnecessary. Also some housekeeping.
/// The fixed withdrawal amount in wei (10 BTC equivalent). | ||
const FIXED_WITHDRAWAL_WEI: U256 = u256_from(10 * WEI_PER_BTC); |
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.
Is there a feasible path to making this configurable? Maybe make it a field for the precompile? Since we know we will support multiple withdrawal quantities. It would still end up being fixed, but there's no reason to hardcode it this low down in the impl.
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 other thing is these defs might make more sense to be in constants.py or even just a json file in a new contrib toplevel dir.
evmctx.journaled_state.log(Log { | ||
address: BRIDGEOUT_ADDRESS, | ||
data: logdata, | ||
}); | ||
|
||
// burn value sent to bridge | ||
let Ok((account, _)) = evmctx.load_account(BRIDGEOUT_ADDRESS) else { | ||
// should never happen | ||
return Err(PrecompileErrors::Fatal { | ||
msg: "could not load account".into(), | ||
}); | ||
}; | ||
|
||
let (new_balance, overflow) = account.info.balance.overflowing_sub(value); | ||
if overflow { | ||
// should never happen | ||
return Err(PrecompileErrors::Fatal { | ||
msg: "invalid balance".into(), | ||
}); | ||
} | ||
// Burn value sent to bridge by adjusting the account balance of bridge precompile | ||
let (account, _) = evmctx | ||
.load_account(BRIDGEOUT_ADDRESS) |
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 too, these don't need to be hardcoded, it's fine to read them from a field.
.ok_or_else(|| PrecompileErrors::Fatal { | ||
msg: "Insufficient balance in BRIDGEOUT_ADDRESS account".into(), | ||
})?; |
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.
Should this revert the whole tx execution? If my understanding is correct this would be an exceptional case (as the comment mentions). See also comment about unconditionally setting to 0 anyways.
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.
updated. setting it directly to zero
}); | ||
} | ||
|
||
account.info.balance = new_balance; |
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.
So shouldn't we just unconditionally set it to 0 then? Instead of doing the checked_sub
that we expect will always go to zero? We can add a sanity check to it to ensure that it's doing it right.
crates/reth/node/src/evm.rs
Outdated
crate::precompiles::bridge::BRIDGEOUT_ADDRESS, | ||
ContextPrecompile::ContextStateful(Arc::new( | ||
crate::precompiles::bridge::BridgeoutPrecompile::default(), | ||
crate::precompiles::bridge::BridgeoutPrecompile, |
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.
Is this fully-qualified crate::
import conventional?
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.
updated
Description
@delbonis please reject this PR if you are already working on this.
Type of Change
Checklist
Related Issues