Terabethia is a blockchain bridge (starting with Ethereum & Internet Computer) that allows contracts to communicate across chains, and assets to be bridged automatically.
February 8, 2022
It’s been a month since the release of Terabethia’s Testnet! We’re following up with V2 of this testnet, receiving some architecture upgrades focused on internalizing and obfuscating data.
Terabethia crossed the 1-month mark with a live testnet on the Internet Computer. For the past month and a half, developers started testing and building on top of the bridge and its communication protocol that helps bridge contracts across Ethereum and the Internet Computer
A month later, with feedback under our arms and more research on our team’s end, we are releasing V2 of Terabethia’s testnet. Our focus with this release? To improve security, make IC -> Eth messages more cheap and efficient using Starknet, and polish the overall architecture!
Let’s dive deep into how the testnet works, what is new, and review the flow in both directions:
Sending messages Ethereum to the Internet Computer
And from the Internet Computer to Ethereum
If you want to get right to testing, visit our updated documentation!
Any Ethereum contract can send messages through Terabethia to a canister on the Internet Computer by calling:
Terabethia.sendMessage(uint256 canisterId, uint256[] payload).
We store only the hash of the message (32 bytes), allowing anyone to efficiently send even large payloads.
Terabethia Goerli contract: 0x2E130E57021Bb4dfb95Eb4Dd0dD8CFCeB936148a
Once you submit the transaction to Ethereum, it’s picked up by our AWS Lambda. If the transaction is valid, we take the uncompressed message data and forward the message to Terabethia’s contract on the IC.
The message is then automatically delivered by calling the handler method on your canister. It’s up to your canister if you decide to consume the message. We provide an example below using eth_proxy .
Once the message is consumed from Terabethia (by calling consume_message), it’s gone and it can’t be consumed anymore. So it’s your responsibility to make sure your flow after consume_message is failure-proof.
We created the eth_proxy example with two versions of how to consistently handle messages from our Terabethia canister. This example uses Terabethia to build two contracts that bridge a token (in this case testnet ETH) to the IC.
The first version will make the proxy an extension to a set token (i.e. DIP20, ERC721); allowing all the functionality to exist within one canister avoiding any inconsistencies with inter canister calls. The second version will build on top of the current version to maintain an internal log of received messages. Allowing manual (using heartbeat function) failure recovery to transactions between a proxy and the respective token.
This version of IC Terabethia focuses on internalizing and obfuscating data. Previously we didn’t have nonce on incoming messages. So with nonce now provided in the message we can maintain idempotency even with the same message.
Similarly we now maintain an internal index (outgoing_nonce) of outgoing messages to Ethereum. Hashing the unique index with the message allows us to create a unique transaction list.
Another update here is that, when consuming a message received from the IC, the Terabethia contract on Ethereum will consume the message from our new Starknet core contract, which we now utilize to relay messages from the IC to Ethereum in a more efficient manner (more on this below).
TerabethiaCanister.send_message(to: Principal, payload: Vec<Nat>).
That store’s outgoing message (hash only) on Terabethia canister.
Terabethia Internet Computer canister: timop-6qaaa-aaaab-qaeea-cai
We pull these messages by our AWS Lambda every minute. Every message is sent to Ethereum through our Starknet Cairo contract. The main difference is messages sent to Ethereum are not automatically triggered (because of gas costs). Once the message is accepted on Ethereum, a user needs to manually consume the message.
As an example, you can check our EthProxy.sol, where users can invoke withdraw(uint256 amount). You can only withdraw the exact amount you burnt on the Internet Computer.
Usually, it takes less than an hour for the message to be accepted on Ethereum, depending on Starknet, but it could be sped up by providing payment.
In V2 of Terabethia, we shifted to integrate Starknet directly into our stack to act as a more efficient relayer of messages from the IC to Ethereum. As detailed in the flow above, messages are sent to our Starknet Cairo contract, which then rolls up to Ethereum. One of the biggest benefits of this is having Starknet handle Ethereum state updates, which can be expensive and challenging to deal with otherwise.
We have also further developed and upgraded our AWS infrastructure and lambda setups to ensure several security guarantees to different aspects of the bridge, and its interactions with Starknet. Let’s dig into the technical details of these security improvements.
We’ll share more on how we plan to reduce our AWS impact/infra in the future below. It’s on our roadmap to reduce centralized components as the bridge grows and new updates allow for it.
Internet Computer Signatures
We’ve secured the sending of messages from Ethereum→ Internet Computer with an secp256k1 key stored in AWS KSM, which means the private key never leaves the HSM (Hardware Security Module). Yes, even our developers don’t have access to it. We only know the public key (Principal ID), which is needed for whitelisting on the IC.
The signing action (ksm:sign) is disabled for everyone, except the lambda roles which are responsible for polling/sending messages (to the IC).
Starknet Signatures
Since Starknet does not support secp256k1 signatures, we are working on an implementation ourselves. In the meantime, we have another AWS KSM key that’s used for decrypting Starknet’s private key.
But how was it encrypted in the first place? For this purpose we have a simple bootstrap Lambda, it creates a random key pair for Starknet and it only exposes Stark address and encrypted private key in base64 format. The Stark address is used when we deploy Cairo contracts (whitelisting operator) and an encrypted private key is set as env variable on the Lambda that sends messages to Starknet.
Encrypting via ksm:encrypt is only allowed to bootstrap the Lambda role. Decrypting via ksm:decrypt is only allowed to a Lambda that sends messages to Starknet.
Reducing Our AWS Impact in the Future
There are two key pieces that we’re looking to tackle in terms of reducing our AWS involvement in Terabethia:
Threshold Signatures — once it’s possible to make signatures within an IC canister, we can leverage these instead of using KMS. Every outgoing message in Terabethia IC would be signed and such signature will be simply verified in Cairo.
Ethereum Integration — once it’s possible to query Ethereum state directly from an IC canister, we can easily check if the Ethereum→Internet Computer message exists there. That way would only use AWS for triggering a message’s delivery, while the message validation would happen on the IC directly.
That’s all for this testnet update! V2 is coming as a great one-up to the initial release of Terabethia, and we’re moving smoothly along towards mainnet!
What are some of the pieces that we’ll be working on to get there?
Exploring batch messages through Starknet to increase throughput
Add and verify secp256k1 signatures on Starknet
Build a transaction or notification checker for IC to ETH pending messages
Magic Proxy (ERC20 asset bridge) built using this new bridge setup
Stay tuned and sharp for more updates! Connect with us on Twitter or Discord to share with the team behind Terabethia.
What’s Next & Wrapping it up!
Security Guarantees
What is New in ICETH in Testnet V2?
When sending messages from the Internet Computer to Ethereum with Terabethia, it’s pretty much the same as the other way around! Any IC canister can call:
Messages From Internet Computer Ethereum
What is New in ETHIC in Testnet V2?
Messages From Ethereum Internet Computer