omni / poa-bridge

POA <-> Ethereum bridge for self transfers of POA native token to POA20 (ERC20 representation). Not supported. Use TokenBridge instead
https://github.com/poanetwork/token-bridge
GNU General Public License v3.0
80 stars 38 forks source link

(Epic) Reverse bridge logic in order to do all expensive confirmations on HomeContract side #5

Open akolotov opened 6 years ago

akolotov commented 6 years ago

Background

The basis of the bridge operations is events EVM sends as part of contract execution. Every bridge instance is looking for new events and as soon as an event appears after transaction applying from a new block, the bridge performs an action.

For example, when an account sends ether to the brigde contract in the Home side of the bridge (the left side), Deposit events is produced. The bridge instance catches this event and creates transaction on the Foreign (right) side to invoke deposit() method of the bridge contract. This transaction is considered as a bridge signature under the fact that some user transfers asset to the Foreign network.

<a href="https://www.websequencediagrams.com/cgi-bin/cdraw?lz=dGl0bGUgYnJpZGdlIGRlcG9zaXQgKHNpbXBsZSBmbG93KQoKcGFydGljaXBhbnQgIkhvbWUgQWNjb3VudCIgYXMgSEEADhNzaWRlXG5Db250cmFjACEHQwA7DkIAbwVcbkluc3RhbmNlAEgFQjEAYA5Gb3JlaWduADwURkMKCkhBLT4rSEM6IGV0aGVyCm5vdGUgbGVmdCBvZiBIQwogICAgYXNzb3NpYXRlZAAKBXdpdGggdHggaWQKZW5kIG5vdGUKSEMtPi1CMTogRACBegYoc2VuZGVyLCB2YWx1ZSkAUQZvdmVyIEIxAEwIdW1lZCB0aGF0AGAFACsGID09IHJlY2lwaWVudABVCkIxLT5GQzoAglYIKAAaCQBaBywAgQoGKQo&s=rose" target="_blank"> <img src="https://www.websequencediagrams.com/cgi-bin/cdraw?lz=dGl0bGUgYnJpZGdlIGRlcG9zaXQgKHNpbXBsZSBmbG93KQoKcGFydGljaXBhbnQgIkhvbWUgQWNjb3VudCIgYXMgSEEADhNzaWRlXG5Db250cmFjACEHQwA7DkIAbwVcbkluc3RhbmNlAEgFQjEAYA5Gb3JlaWduADwURkMKCkhBLT4rSEM6IGV0aGVyCm5vdGUgbGVmdCBvZiBIQwogICAgYXNzb3NpYXRlZAAKBXdpdGggdHggaWQKZW5kIG5vdGUKSEMtPi1CMTogRACBegYoc2VuZGVyLCB2YWx1ZSkAUQZvdmVyIEIxAEwIdW1lZCB0aGF0AGAFACsGID09IHJlY2lwaWVudABVCkIxLT5GQzoAglYIKAAaCQBaBywAgQoGKQo&s=rose" alt="bridge deposit (flow with 3 bridges in action)" width="550" />

In order to achieve availability and reliability, there are more than one bridge instances (N). During these bridges configuration it is settled that just subset (M, M <= N) of them is enough to transit the state between two networks. So, if M bridges confirmed the same state transition operation (deposit), this state committed on the opposite side of the bridge:

<a href="https://www.websequencediagrams.com/cgi-bin/cdraw?lz=dGl0bGUgYnJpZGdlIGRlcG9zaXQgKGZsb3cgIHdpcmggMwAWB3MgaW4gYWN0aW9uKQoKcGFydGljaXBhbnQgIkhvbWUgQWNjb3VudCIgYXMgSEEADhNzaWRlXG5Db250cmFjACEHQwA7DkIAgQIFXG5JbnN0YW5jZSAjMQBLBUIxAAggMgAiBjIAMCAzAEoGMwCBMw5Gb3JlaWduAIEPFEZDCgpIQS0-K0hDOiBldGhlcgpub3RlIGxlZnQgb2YgSEMKICAgIGFzc29zaWF0ZWQACgV3aXRoIHR4IGlkCmVuZCBub3RlCkhDLT5CMTogRACCXwYoc2VuZGVyLCB2YWx1ZSkAGQYyAAIdLUIzACYZAIEQBW92ZXIgQjEsIEIyLCBCMwCBEgh1bWVkIHRoYXQAgSYFAHIGID09IHJlY2lwaWVudACBGwpCMS0-K0ZDOgCEAwgoABsJAIEiBywAgVEGKQpGQy0-LUZDOiAxc3Qgc2lnbmF0dXJlIHJlY2VpdmVkCkIyABkxMm5kADUVMwBoLEZDOiAzcgA0FQCBKgkic3RhdGVcbmNvbW1pdGVkIgo&s=rose" target="_blank"> <img src="https://www.websequencediagrams.com/cgi-bin/cdraw?lz=dGl0bGUgYnJpZGdlIGRlcG9zaXQgKGZsb3cgIHdpcmggMwAWB3MgaW4gYWN0aW9uKQoKcGFydGljaXBhbnQgIkhvbWUgQWNjb3VudCIgYXMgSEEADhNzaWRlXG5Db250cmFjACEHQwA7DkIAgQIFXG5JbnN0YW5jZSAjMQBLBUIxAAggMgAiBjIAMCAzAEoGMwCBMw5Gb3JlaWduAIEPFEZDCgpIQS0-K0hDOiBldGhlcgpub3RlIGxlZnQgb2YgSEMKICAgIGFzc29zaWF0ZWQACgV3aXRoIHR4IGlkCmVuZCBub3RlCkhDLT5CMTogRACCXwYoc2VuZGVyLCB2YWx1ZSkAGQYyAAIdLUIzACYZAIEQBW92ZXIgQjEsIEIyLCBCMwCBEgh1bWVkIHRoYXQAgSYFAHIGID09IHJlY2lwaWVudACBGwpCMS0-K0ZDOgCEAwgoABsJAIEiBywAgVEGKQpGQy0-LUZDOiAxc3Qgc2lnbmF0dXJlIHJlY2VpdmVkCkIyABkxMm5kADUVMwBoLEZDOiAzcgA0FQCBKgkic3RhdGVcbmNvbW1pdGVkIgo&s=rose" alt="bridge deposit (simple flow)" width="750" />

This is a basic scenario which is enough to transite state between two EVM-based networks. The maximum (for the third bridge) gas consumption of deposit operation is about 90000.

The use case considered by parity-bridge (https://github.com/paritytech/parity-bridge, commit ceaf22f) is to connect Ethereum Foundation (Home side) and a private PoA networks (Foreign side). So, it is assumed that we need to keep as cheap as possible transactions on the Home side whereas consumption of the gas on the Foreign side does not make much sense. This is due to the reason that most probably bridge instances are managed/supported by owners of the PoA network so almost infinite resources could be spent to maintain transactions from bridges within the PoA network.

That is why the original development of parity-bridge is focused on the reduce number of transactions and gas consumption for operations made on the Home side of the brige. In order to transit the state from the Home to the Foreign network three bridges will send three transactions. And only one bridge is being chosen to perform state transition from the Foreign side to Home.

It becomes posisble owing to the architecture when confirmations of bridges to transfer the state are collected on the Foreign side (remember that it costs nothing) and as soon as needed number of confirmation gathered the bridge which sent the latest confirmation is responsible for forwarding all signatures (which are part of the confirmations) to the Home side.

<a href="https://www.websequencediagrams.com/cgi-bin/cdraw?lz=dGl0bGUgcGFyaXR5LWJyaWRnZSB3aXRoZHJhdyBmbG93IChvcmlnaW5hbCkKCnBhcnRpY2lwYW50ICJIb21lIEFjY291bnQiIGFzIEhBAA4Tc2lkZVxuQ29udHJhYwAhB0MAOw5CAHIFXG5JbnN0YW5jZSAjMVxuKEJJICMxKQBUBUIxABEgMgAqBzIAKgcyAEIgMwBbBzMAWwczAIFODkZvcmVpZ24AgSoURgCBLw8AIwgAgX4MRkEKCm5vdGUgcmlnaHQgb2YgRkEKICAgIGJhbACBXQV0cmFuc2ZlcgAQBXNpbWlsYXIgdG8gRVJDLTIwIHRva2VuCmVuZCBub3RlCkZBLT4rRkM6ICJleHRlcm5hbAA4CVxuKHJlY2lwaWVudCwgdmFsdWUpIgBsEEMAdwVhc3Nvc2lhdGVkAIEGBXdpdGggdHggaWQAXgtDLT5CMzogVwCDewcAShIAHQYxAAIhLUIyACodQjEAgUwHc3VibWl0U2lnbmF0dXJlKHNpZywgAIFDECwAgSMGAFQHRkM6IDFzdCBzaWcgcmVjZWl2ZWQKQjMAEz4ybmQAQg8yAGk5RkM6IDNyAEEPAIQLBWxlZgCDBwxzZW5kZXIgPT0gQkkgYWRkcmVzcwCEIwVoYXNoID09AAMFAINQEQCCBQkAgyoOMjogQ29sbGVjdGVkAIJHCXMoAF4GLABOBQCDNQoABCYtQjMAMSRCMgCBbgYibWVzc2FnZSgAZwVcbnMAg00JaGFzaCwgMXN0AAMTMm5kABkTM3JkKSIAgVAJbGlzAIZCBQBJCXMAhAwZAIMzBkhDOiAiAIlBCCgALBNcbgCETRgiCkhDLT5IQTogZXRoZXIK&s=rose" target="_blank"> <img src="https://www.websequencediagrams.com/cgi-bin/cdraw?lz=dGl0bGUgcGFyaXR5LWJyaWRnZSB3aXRoZHJhdyBmbG93IChvcmlnaW5hbCkKCnBhcnRpY2lwYW50ICJIb21lIEFjY291bnQiIGFzIEhBAA4Tc2lkZVxuQ29udHJhYwAhB0MAOw5CAHIFXG5JbnN0YW5jZSAjMVxuKEJJICMxKQBUBUIxABEgMgAqBzIAKgcyAEIgMwBbBzMAWwczAIFODkZvcmVpZ24AgSoURgCBLw8AIwgAgX4MRkEKCm5vdGUgcmlnaHQgb2YgRkEKICAgIGJhbACBXQV0cmFuc2ZlcgAQBXNpbWlsYXIgdG8gRVJDLTIwIHRva2VuCmVuZCBub3RlCkZBLT4rRkM6ICJleHRlcm5hbAA4CVxuKHJlY2lwaWVudCwgdmFsdWUpIgBsEEMAdwVhc3Nvc2lhdGVkAIEGBXdpdGggdHggaWQAXgtDLT5CMzogVwCDewcAShIAHQYxAAIhLUIyACodQjEAgUwHc3VibWl0U2lnbmF0dXJlKHNpZywgAIFDECwAgSMGAFQHRkM6IDFzdCBzaWcgcmVjZWl2ZWQKQjMAEz4ybmQAQg8yAGk5RkM6IDNyAEEPAIQLBWxlZgCDBwxzZW5kZXIgPT0gQkkgYWRkcmVzcwCEIwVoYXNoID09AAMFAINQEQCCBQkAgyoOMjogQ29sbGVjdGVkAIJHCXMoAF4GLABOBQCDNQoABCYtQjMAMSRCMgCBbgYibWVzc2FnZSgAZwVcbnMAg00JaGFzaCwgMXN0AAMTMm5kABkTM3JkKSIAgVAJbGlzAIZCBQBJCXMAhAwZAIMzBkhDOiAiAIlBCCgALBNcbgCETRgiCkhDLT5IQTogZXRoZXIK&s=rose" alt="bridge withdraw (flow, 3 bridges)" width="850" />

The procedure to confirm the state transition (submitSignature) is the most expensive one. It consumes about 270000 gas (if it was sent to provide a final signature) since requires lots of mathematical operations and use the contract storage extensively.

Here is the list gas consumption for all operations performed by bridge:

Handling deposit() on the Foreign side (deposit_relay) = 90861, every bridge instance
Handling submitSignature() on the Foreign side (withdraw_confirm) = 265380, every bridge instance
Handling withdraw() on the Home side (withdraw_relay) = 72444, one bridge instance

Relatively huge gas consumption is the only the reason why patity-bridge is not recommended to be used with Ethereum Foundation network in the right side: the meaningless from the state transaction confirmation operation will cost ~5 USD (exchange rate 1000 USD per 1 ether). But cases when a PoA network is on the Home side and the Ethereum Foundation network is on the Foreign side make sense since they allow to split transactions traffic between two networks which could have positive effect on network performance and transactions fees.

Proposal for costs optimization

From the analysis above it is evident that most costly transactions happens on the right side of the bridge. So, if Ethereum Foundation network is there so it will not be cost effective to send several transaction to confirm the deposit and several transaction to confirm the withdraw.

It means that all operations for confirmation should happens on the left side of the bridge and it equals of mirroring handling of confirmation for the current implementation:

  1. As soon as a user deposits coins, validators confirmations must be gathered on the left side of the bridge. It will be called deposit_confirm.
  2. When last confirmation received, one validator (one which sent the final confirmation) is responsible for forwarding the confirmation to the right side: deposit_relay.
  3. If a user sends request to exchange tokens to coins, the Withdraw event is handled and every bridge instance sends the confirmation directly to the left side of the bridge. It is withdraw_relay.

<a href="https://www.websequencediagrams.com/cgi-bin/cdraw?lz=dGl0bGUgUG9BIENUVCBicmlkZ2UgZGVwb3NpdCAoMwALB3MpCgpwYXJ0aWNpcGFudCAiSG9tZSBBY2NvdW50IiBhcyBIQQAOE3NpZGVcbkNvbnRyYWMAIQdDADsOQgBtBVxuSW5zdGFuY2UgIzFcbihCSSAjMSkAVAVCMQARIDIAKgcyACoHMgBCIDMAWwczAFsHMwCBTg5Gb3JlaWduAIEqFEYAgS8PACMIAIF-DEZBCgpIQS0-K0hDOiAiY29pbnMiCm5vdGUgcmlnaHQgb2YgSEMKICAgIGFzc29zaWF0ZWQACgV3aXRoIHR4IGlkCmVuZCBub3RlCkhDLT5CMzogRACDDAYoc2VuZGVyLCB2YWx1ZSkAGQYxAAIdLUIyADgHAC0RAIEQBW92ZXIgQjEsIEIyLCBCMwCBEQh1bWVkIHRoYXQAgSUFAHEGID09IHJlY2lwaWVudACBGgpCMQCBZgdzdWJtaXRTaWduYXR1cmUoc2lnLAAnCgCBLgcsAIFdBgCBFgdIQzogMXN0IHNpZyByZWNlaXZlZApCMwATPjJuZABCDzIAaTlIQzogM3IAQQ8AgzkVAIIaCkJJIGFkZHJlc3MAg2IFaGFzaCA9PQADBSgAgXYZAINlDjI6IENvbGxlY3RlZACCSAlzAIN2CWhhc2gAg3QKAAQmLUIzADEkQjIAgW8GIm1lc3NhZ2UoAGcFXG5zAINOCWhhc2gsIDFzdAADEzJuZAAZEzNyZCkiAIFQCWxpcwCGAQUASQlzAIQNGQCDNAZGQzogIgCJDQcoACsTXG4AhE0YIgpGQy0-LUZBOiB0b2tlbnMK&s=rose" target="_blank"> <img src="https://www.websequencediagrams.com/cgi-bin/cdraw?lz=dGl0bGUgUG9BIENUVCBicmlkZ2UgZGVwb3NpdCAoMwALB3MpCgpwYXJ0aWNpcGFudCAiSG9tZSBBY2NvdW50IiBhcyBIQQAOE3NpZGVcbkNvbnRyYWMAIQdDADsOQgBtBVxuSW5zdGFuY2UgIzFcbihCSSAjMSkAVAVCMQARIDIAKgcyACoHMgBCIDMAWwczAFsHMwCBTg5Gb3JlaWduAIEqFEYAgS8PACMIAIF-DEZBCgpIQS0-K0hDOiAiY29pbnMiCm5vdGUgcmlnaHQgb2YgSEMKICAgIGFzc29zaWF0ZWQACgV3aXRoIHR4IGlkCmVuZCBub3RlCkhDLT5CMzogRACDDAYoc2VuZGVyLCB2YWx1ZSkAGQYxAAIdLUIyADgHAC0RAIEQBW92ZXIgQjEsIEIyLCBCMwCBEQh1bWVkIHRoYXQAgSUFAHEGID09IHJlY2lwaWVudACBGgpCMQCBZgdzdWJtaXRTaWduYXR1cmUoc2lnLAAnCgCBLgcsAIFdBgCBFgdIQzogMXN0IHNpZyByZWNlaXZlZApCMwATPjJuZABCDzIAaTlIQzogM3IAQQ8AgzkVAIIaCkJJIGFkZHJlc3MAg2IFaGFzaCA9PQADBSgAgXYZAINlDjI6IENvbGxlY3RlZACCSAlzAIN2CWhhc2gAg3QKAAQmLUIzADEkQjIAgW8GIm1lc3NhZ2UoAGcFXG5zAINOCWhhc2gsIDFzdAADEzJuZAAZEzNyZCkiAIFQCWxpcwCGAQUASQlzAIQNGQCDNAZGQzogIgCJDQcoACsTXG4AhE0YIgpGQy0-LUZBOiB0b2tlbnMK&s=rose" alt="PoA CTT bridge deposit (3 bridges)" width="850" />

<a href="https://www.websequencediagrams.com/cgi-bin/cdraw?lz=dGl0bGUgUG9BIENUVCBicmlkZ2Ugd2l0aGRyYXcgKDMADAdzKQoKcGFydGljaXBhbnQgIkhvbWUgQWNjb3VudCIgYXMgSEEADhNzaWRlXG5Db250cmFjACEHQwA7DkIAbgVcbkluc3RhbmNlICMxAEsFQjEACCAyACIGMgAwIDMASgYzAIEzDkZvcmVpZ24AgQ8URgCBFA8AIwgAgWMMRkEKCm5vdGUgbGVmdCBvZiBGQQogICAgYmFsYW5jZVxudHJhbnNmZXIKZW5kIG5vdGUKRkEtPitGQzogdG9rZW5zADAPQwA6BWFzc29zaWF0ZWQASQV3aXRoIHR4IGlkADwLQy0-QjE6IFcAgx4HKHNlbmRlciwgdmFsdWUpABoGMgACHi1CMwAnGgCBUgVvdmVyIEIxLCBCMiwgQjMAgRUIdW1lZCB0aGF0AIFoBQB0BiA9PSByZWNpcGllbnQAgWUKQjEtPitIQzoAhEUJKAAcCSxcbgCBKAUsAIFWBikKSEMtPi1IQzogMXN0IHNpZ25hdHVyZVxucmVjZWl2ZWQKQjIAMxoAgXMGADoSMm5kADYWMwAfLUhDOiAzcgA1FgAYCCJzdGF0ZVxuY29tbWl0ZWQiAIFLB0E6IGNvaW5zCg&s=rose" target="_blank"> <img src="https://www.websequencediagrams.com/cgi-bin/cdraw?lz=dGl0bGUgUG9BIENUVCBicmlkZ2Ugd2l0aGRyYXcgKDMADAdzKQoKcGFydGljaXBhbnQgIkhvbWUgQWNjb3VudCIgYXMgSEEADhNzaWRlXG5Db250cmFjACEHQwA7DkIAbgVcbkluc3RhbmNlICMxAEsFQjEACCAyACIGMgAwIDMASgYzAIEzDkZvcmVpZ24AgQ8URgCBFA8AIwgAgWMMRkEKCm5vdGUgbGVmdCBvZiBGQQogICAgYmFsYW5jZVxudHJhbnNmZXIKZW5kIG5vdGUKRkEtPitGQzogdG9rZW5zADAPQwA6BWFzc29zaWF0ZWQASQV3aXRoIHR4IGlkADwLQy0-QjE6IFcAgx4HKHNlbmRlciwgdmFsdWUpABoGMgACHi1CMwAnGgCBUgVvdmVyIEIxLCBCMiwgQjMAgRUIdW1lZCB0aGF0AIFoBQB0BiA9PSByZWNpcGllbnQAgWUKQjEtPitIQzoAhEUJKAAcCSxcbgCBKAUsAIFWBikKSEMtPi1IQzogMXN0IHNpZ25hdHVyZVxucmVjZWl2ZWQKQjIAMxoAgXMGADoSMm5kADYWMwAfLUhDOiAzcgA1FgAYCCJzdGF0ZVxuY29tbWl0ZWQiAIFLB0E6IGNvaW5zCg&s=rose" alt="PoA CTT bridge withdraw (3 bridges)" width="850" />

Changes required:


  1. Optimization of the ForeignBridge contract:
    • remove submitSignature(), signature() and message();
    • remove the corresponding maps keeping information about signatures;
    • rework deposit() to work with list of signatures similarly to withdraw() of the original HomeBridge contract;
    • consider to have the code to cover costs of the bridge (isMessageValueSufficientToCoverRelay(), getWithdrawRelayCost() and estimatedGasCostOfWithdraw)
  2. Modification of the HomeBridge contract:
    • rework withdraw() to accept signatures directly from bridge validators similar to deposit() method on the original ForeignBridge contract.
    • there is no need any more to cover costs of the bridge on the Home side so isMessageValueSufficientToCoverRelay(), getWithdrawRelayCost() and estimatedGasCostOfWithdraw must be removed.
    • introduce submitSignature(), signature() and message() and corresponding maps to keep information about signatures similarly to the original ForeignBridge contract.
  3. Rework bridge/src/bridge/withdraw_relay.rs to send withdraw() to the HomeBridge contract as soon as Withdraw event appeared on the Foreign side. Every bridge instance should invoke this method simiarly deposit() of the original HomeBridge contract.
  4. Rework bridge/src/bridge/deposit_relay.rs to wait for CollectedSignatures and forward deposit with the list of signatures to the ForeignBridge contract.
  5. Rename bridge/src/bridge/withdraw_confirm.rs to bridge/src/bridge/deposit_confirm.rs and modify it as so Deposit event is being waited from Home side and submitSignature() is invoked by every bridge instance. The corresponding changes must be made in bridge/src/bridge/mod.rs in order to run the confirmation module.
  6. Modify bridge/src/database.rs and bridge/src/bridge/mod.rs to not track checked_withdraw_confirm in the database and update checked_deposit_confirm instead.
  7. Modify bridge/src/config.rs to
    • get rid of options transaction.withdraw_confirm.gas, transaction.withdraw_confirm.gas_price.
    • introduce options transaction.deposit_confirm.gas, transaction.withdraw_deposit.gas_price.
akolotov commented 6 years ago

Actually it is an epic for changes in both parts: solidity and rust. Since we agreed that reverse logic of contract is not the priority just now, I would leave this issue as is till the time we have enough resources to address it.

akolotov commented 6 years ago

Changes on Solidity (and contract deployment) side already made: https://github.com/poanetwork/poa-bridge-contracts/tree/v2.