1. Home
  2. coinbase-eng

coinbase-eng

Announcing Coinbase’s successful transition to React Native

By Harry Tormey

As of January 2021, the Coinbase iOS and Android apps have transitioned away from native development to React Native, and all mobile engineers are now collaborating in a single codebase. The transition from native to React Native did not happen overnight, and in the interest of helping those contemplating such a decision, we want to tell the story of how we got here. Specifically, we want to share our deliberate and methodical process of testing and observing results, then upping the stakes with increasingly more impactful trials, as this approach was critical to the migration’s success.

To put the impact of this technological shift in perspective, Coinbase provides financial services to 56 million users and generated $1.8 billion in revenue in Q1 2021 alone. Regressions in features or lackluster performance could have serious implications for our customers and our business.

The size of our native codebases was also notable. Migrating to React Native meant reimplementing over 200 screens, many of which contained substantial business logic. The transition also involved retraining our 30+ native engineers while continuing to make progress building new features and sunsetting our legacy apps. There were many moving pieces, but we were able to deliver significant product performance improvements at each stage of the migration.

When Coinbase was founded in 2012, it only had a website — we began our mobile program in 2013. The first iOS and Android apps we released were native, written in Objective-C and Java, respectively.

By 2017, we had a small team of Android and iOS engineers working on these apps, but despite our best efforts, we were having a hard time scaling. Over the course of that year, we were only able to hire half as many mobile engineers as web engineers. Furthermore, while web engineers saw notable productivity gains, the average mobile engineer’s velocity remained stagnant. As our scaling efforts continued to yield disappointing results into 2018, it became increasingly clear that we needed to increase our rate of growth and speed of iteration on mobile platforms.

A change in strategy was needed, so we decided to take a step back and think about how we build products from a first-principles perspective. At Coinbase, major features are built and maintained by cross-functional teams, typically consisting of 2 backend engineers and 2 frontend engineers for each supported platform (web, iOS, and Android). This structure required a large number of engineers to maintain a single vertical of our product. It also meant that engineers were somewhat siloed from other engineers working on the same platform, making it difficult to coordinate larger, systemic changes.

Thinking from this perspective led us to ask the question: What if we could reduce a healthy feature team from 8 — with each client engineering pair being isolated on a separate platform — to 5 engineers — where multiple client engineers could work across all three platforms.

We hypothesized that this could dramatically reduce our overall staffing requirements, improve our team’s effectiveness, and increase the connectedness of engineers on our client platforms. At the same time, we also believed that gaining efficiency couldn’t be the only goal; any technology change we made also had to deliver improved quality and performance for our customers. This line of thinking led us to start looking at different cross-platform technologies.

At this stage, we already had a well-functioning web engineering platform, which was built on React. After exploring a number of different cross-platform technology platforms, we decided that React Native would be the best choice for us. It leveraged a technology stack we already knew and offered a clear path to even further consolidation across both mobile and web.

Once we had reached alignment with regard to the technology platform, we created a plan to gradually explore it across our product surfaces. We wanted to de-risk the migration by starting with lower-stakes areas, then gradually increase scope and impact as we developed competence and confidence. After a few months of preliminary research, we landed on a 3-part strategy:

  • Start with a greenfield exploration. We decided that the first place to experiment with React Native was a fully greenfield environment, where we could evaluate the technology without the complexity of native <> React Native integrations. From a frontend perspective, Pro was our most performance-intensive and complex product, and users had been asking for a mobile app for some time. It seemed like a perfect candidate for our explorations. If React Native could handle the Pro mobile app’s requirements — which involved technically challenging aspects like real-time price and depth charts — we would have a high degree of confidence that it could satisfy the needs of our other products. The project would also allow us to also allow us to assess developer velocity and be sure that we could cross train our web engineers to be effective React Native engineers.
  • Explore what a brownfield rewrite would look like. The next area we decided to explore was a brownfield integration, where we would incorporate React Native into an existing native app. We set out to rebuild our onboarding flows with React Native, then share them between the Pro mobile app (React Native) and the main Coinbase iOS and Android apps (both native). Coinbase currently supports over 100 countries, and because different jurisdictions have different regulatory requirements, our sign-up experience needs to be dynamic — adapting to each user’s location and identity profile. These flows were some of the oldest, most complex parts of our mobile apps; even incremental changes could be expensive to implement. With the launch of a standalone Pro product, reimplementing them twice would have been extremely expensive so we saw the opportunity here to both explore React Native in a brownfield environment and create a shared onboarding flow between the two apps.
  • Building on lessons learnt developing these greenfield and brownfield solutions, execute a complete rewrite of our core product. If we were successful in the first two stages, we hypothesized we could execute a complete rewrite of the main Coinbase app in React Native. When we initially created the strategy, we weren’t sure whether this rewrite would be an incremental brownfield rewrite (where we rewrote screens gradually) or a greenfield rewrite (where we started from scratch). We left this implementation detail open to what we learned from our first two phases.

With our long-term strategy in place, we got started with the Pro mobile app. After 6 months of building, the Pro mobile app was released in October 2019 and exceeded our expectations. We saw positive business results, built a good understanding of performance challenges (and solutions) on the platform, and began to fully appreciate the step function change in developer productivity possible with React Native. It also showed us that web engineers could become effective React Native developers in a relatively short period of time.

Encouraged by our success with the Pro mobile apps, we started phase 2 — a brownfield rewrite of our onboarding flows. The project started in mid-2019 and shipped 6 months later, once again meeting the goals we set for quality and business metrics. Because the onboarding module was written in React Native, it was able to be shared between the Coinbase and the Pro mobile apps.

While the outcome of the onboarding rewrite was undoubtedly positive, the brownfield approach did have its challenges. For example, each change to the onboarding module would require rebuilding a package with native bindings, then rebuilding native apps using the shared module to manually test. This could be a particularly frustrating process for engineers who only had web or native experience, as iterating on the shared code potentially required an understanding of all three platforms. Furthermore, because developing this way could be even more time-consuming than fully native development, it left some engineers — both web and native — wondering why we were bothering with React Native at all.

If you’ve read Airbnb’s excellent Sunsetting React Native article, these challenges may sound familiar. We spent many hours speaking with engineers from Airbnb and trying to learn from their experiences. We’re grateful to the team for sharing the details of their journey, as the information was invaluable in deciding the best path for Coinbase. One of our key takeaways was that the brownfield approach seemed to be core to many of the challenges they faced. While the idea of incrementally migrating is at first glance appealing — leveraging the benefits of React native for new features without the upfront cost of a full rewrite — it introduces significant technical and cultural migration risk over the long term.

With these observations as a backdrop, and two successful projects under our belt, we had the confidence to move forward with replatforming the primary Coinbase mobile app. We decided that:

  1. We would rewrite Android first. We believed Android would be the more difficult of the two platforms and felt that if we could get it right from a quality, performance, and velocity perspective, we’d have a clear path to rolling out on iOS as a fast-follow. Building Android first also allowed us to continue full-steam ahead on native iOS in parallel, ensuring that our customers continued to see experience improvements as we worked on the rewrite.
  2. We would do a fully greenfield rewrite, rather than taking a brownfield / piecemeal approach. Based on our own experiences (with Pro and the onboarding module) and lessons learned from companies like Airbnb, we concluded that brownfield projects increased complexity, introduced risk of getting “stuck” in an in-between state, and created space for prolonged cultural disagreements between engineers on different platforms.

Given the velocity we had seen so far with React Native, we estimated that we could execute a full rewrite of our product in 6 months. We also felt that the upside of having a unified platform at the end of that rewrite outweighed the cost in the event that we ultimately decided to scrap the project. We began replatforming the Android app in March 2020 and delivered the fully rewritten Android application almost exactly 6 months later. We rolled out the rewrite as an experiment and measured results, which showed positive impact across the key metrics we targeted.

With a positive result on Android, we then decided to move forward with replatforming the Coinbase iOS app. We spent the next quarter “catching up” on key features the iOS team had built in parallel to the Android rewrite. We then rolled out the new React Native code base to our iOS customers as an experiment and completed that rollout in late January 2021. Similar to Android, we saw positive impact across the key metrics we targeted. With the launch of React Native on iOS, we had completed the full migration of our product to this new technology platform.

In the middle of 2020, we had roughly seven Android engineers and 18 iOS engineers working on the Coinbase mobile apps. As of today Coinbase’s React Native repo has 113 contributors, including a large number of web engineers, who previously would have been unable to contribute on mobile. We’ve also seen positive results with cross-training our native mobile engineering talent, with little attrition as a result of the technology change. Engineers from both iOS and Android backgrounds are now making high-impact contributions.

Our teams have also begun to structure themselves as we anticipated in 2018, with a unified client team that works across three platforms. Currently, these client teams are not fully fungible across web and mobile, but we’re getting there. And we believe that the transition to React Native is only step one in our path to creating a single, unified, client platform for all Coinbase applications.

We’re now down from 3 to 2 application platforms — React Native and React Web — but we’d like to get down to 1.5, and we have an ambitious roadmap in 2021 to do so. We’re building a cross-platform design system, a universal data layer based on GraphQL, and the foundations needed to converge web and mobile tooling. We imagine a world where engineers can ship a feature across our web and mobile apps with minimal context switching, reinvesting the gains in effectiveness in the quality of our apps.

From idea to final rollout on iOS, we spent two years of gradual exploration, experimentation, and execution. We also believe that we are still at the beginning of what we can accomplish with this unified client platform. A condensed timeline of our research and milestones can be seen below:

2018–12: An engineer shares a proposal for Coinbase to explore the possibilities of React Native as a mobile platform

2019–03: Members from the Coinbase team investigate several technical directions for cross-platform and decide to move forward with React Native

2019–04: Engineering on the Coinbase Pro mobile application begins

2019–07: Engineering on the Unified Mobile Onboarding begins

2019–10: The Coinbase Pro Mobile app is released to the App Store

2019–11: Unified Mobile Onboarding ships on Coinbase.com and Pro

2020–03: We begin the full rewrite of our Coinbase Android application

2020–07: All Android and iOS engineers at Coinbase have the option to go through an in-house training program to ramp up on React Native

2020–10: The rewritten Coinbase app launches on Android and Coinbase commits to replatforming the Coinbase.com iOS app

2021–01: The Coinbase iOS app is rolled out to 100% of our users

In the coming months, we will be publishing more about our experience replatforming a mobile app that is used by over 56 million users around the world. We will be publishing articles that explore the technical challenges of React Native and the lessons we learned along the way. We hope that our app can be a great reference for anyone considering building products at scale using React Native.

If you’re interested in developing React Native technologies and building an open financial system, consider our open roles and apply for a position.

This website contains links to third-party websites or other content for information purposes only (“Third-Party Sites”). The Third-Party Sites are not under the control of Coinbase, Inc., and its affiliates (“Coinbase”), and Coinbase is not responsible for the content of any Third-Party Site, including without limitation any link contained in a Third-Party Site, or any changes or updates to a Third-Party Site. Coinbase is not responsible for webcasting or any other form of transmission received from any Third-Party Site. Coinbase is providing these links to you only as a convenience, and the inclusion of any link does not imply endorsement, approval or recommendation by Coinbase of the site or any association with its operators.

*This information is based on information available to Coinbase as of the date of this release and is subject to the completion of its quarterly financial closing procedures and review by the Coinbase’s independent registered public accounting firm.

All images provided herein are by Coinbase.


Announcing Coinbase’s successful transition to React Native was originally published in The Coinbase Blog on Medium, where people are continuing the conversation by highlighting and responding to this story.

Coinbase Scores Major Legal Win – SEC Stalled by Rare Court Ruling

Production Threshold Signing Service

By Anika Raghuvanshi, Software Engineer on the Crypto Engineering Team

When generating keys to secure customer funds, we take many precautions to ensure keys cannot be stolen. Cryptocurrency wallets are associated with two keys: a secret or private key, known only to the wallet holder, and a public key, known to the world.¹ To send funds from a wallet, the wallet owner produces a valid digital signature, which requires signing a message (a transaction in this case) with their private key. If a malicious party gains access to the private key, they could steal the wallet’s funds. For most customers, Coinbase has the responsibility of protecting private keys to make sure funds remain secure and out of reach of attackers.

Reusable Keys

During key generation, we segment private keys into shares using Shamir Secret Sharing (SSS) and delete the full key for extra security. Each share is held by a different party, and no individual party has full access to the private key. For a long time, there was one way to create a signature: reassemble private key shares to sign a transaction. Therefore, for our wallets to maintain the highest level of security, we only used an address once. If 1 BTC needed to be withdrawn from a key that stores 100 BTC, the remaining 99 BTC would be sent to a new private key during the withdrawal to ensure that we were not storing funds at a potentially vulnerable address.

However, one-time-use addresses have limits. In addition to the overhead required with continuing to generate keys, an even stronger need for securely reusing keys came along with cryptocurrency staking. Staking generally requires multiple uses of a single long-term address. We needed a way to generate valid digital signatures without reconstructing the private key.

Multiparty computation (MPC) saved the day. MPC protocols allow multiple parties to compute a function together, revealing no other information besides the output. Threshold signing, a specific use of MPC, permits individual parties to collaborate and produce a digital signature without reconstituting the original, composite private key. In practice, this means that rather than parties uploading their private key shares, they individually sign a transaction with their key share and upload a partial signature. These partial signatures² are combined to create the valid signature, which is published to the blockchain.³ Key shares are never uploaded by parties nor combined, therefore maintaining the highest security while allowing keys to be reused.

Threshold Signing Service

We applied MPC to create Threshold Signing Service (TSS). Different cryptocurrency assets use different digital signatures algorithms. We will focus the rest of this article on the TSS protocol for Ed25519 signatures. There are five phases for this protocol:

  • Party Key Generation. Creates long-term public and private keys in a trusted environment for parties who will participate in signing. Each party’s private keys are loaded onto Hardware Security Modules (HSMs), which prevent anyone from using the private keys without physical access to the HSM.
  • Key Generation. Creates a set of TSS keys and divides the keys using SSS. Uses the public keys produced in party key generation to encrypt each signing key share to the party who will receive it.
  • Nonce Generation. Round 1 of 2 of the signing protocol. Participants in this round generate nonce values and send them to all other parties.
  • Partial Sign. Round 2 of 2 of the signing protocol. Participants use the nonce shares received from other parties and their signing key share to generate partial signatures.
  • Generate Final Signature. Combine partial signatures into the final result.

The first two phases occur rarely (once in the lifetime of a signing key). The final three phases repeat every time a transaction, which we call a message, is signed. The next section takes a technical deep dive into the signing phases of the protocol.Ed25519 Signatures

The method for generating a digital signature for an Ed25519 key is as follows: Ed25519 is the EdDSA signature scheme that is parameterized to SHA-512 and Curve25519. For elliptic curves, G is the base point and q is the base point order. Given a message m to be signed and a private key k, a signature is produced as follows:

Our threshold signing protocol is an adaptation of the threshold Schnorr signature scheme by Gennaro, Jarecki, Krawczyk, and Rabin.

In the protocol, participants generate both the nonce r and signature s in a distributed fashion without reconstituting the underlying private key. In Round 1, participants produce and distribute nonce shares rᵢ. In Round 2, participants compute the composite nonce r from the nonce shares rᵢ and produce partial signatures sᵢ, which the server combines to produce the composite signature s. The final signature is identical to the signature which would be produced by combining secret shares and signing the original message with the composite private key.

Nonce Generation

In Round 1, participants use the message m and the key share kᵢ to do the following

After t participants have completed the nonce generation, signing begins.

Nonce Aggregation

After t nonces have been posted, participants perform Round 2 by aggregating the nonce shares to derive the composite nonce. Each participant i performs:

Partial Signatures

Participants create partial signatures⁴, which can be combined to generate the signature s.

Each participant i performs:

Signature Aggregation

Finally, the server aggregates components into signature that can be verified with public key K.

Below is an example that combines two partial signatures without Shamir sharing:

As long as the challenge, c, is the same for both signatures, the nonce and private key shares behave linearly under addition. Due to this property, we can apply the standard Shamir’s reconstruction to the sᵢ values to construct s:

This result, along with nonce public key R, is a valid signature. The server verifies the signature (R, s) using message m and public key K and checks the nonce value R has not been previously used.

From Concept to Production

Deploying a production-level system involves solving for certain real-world problems. For example, getting attention from human participants can take a long time (on the order of hours). Since the protocol supports human participants, we run the risk of delaying transaction approval for too long. For example, the cryptocurrency Algorand has a short validation time: just a few hours. If we cannot compute a signature over a transaction in this time frame, partial progress must be discarded. Two of our design decisions help reduce the burden for humans approving transactions: 1. Rounds are asynchronous, meaning participants do not have to participate at the same exact time, and 2. Each round requires a threshold of parties, but both rounds do not require the same set of participants to participate.

Another challenge is the issue of storing secret information, since the devices used to store key shares and participate in the signing protocol could be lost or broken. This led to a model where parties are relatively stateless: the only state they have is a small amount of long term storage on HSMs, which are highly secure, portable, and durable. Participants in the signing protocol do not communicate with each other: a centralized server stores all artifacts, such as nonce shares and partial signatures. A natural concern to come up is what happens if a centralized server is compromised — we investigate this threat and other threat models in the following section.

Security

TSS has two primary security goals:

  1. Without the private key, an attacker should not be able to generate a valid signature over an unauthorized message. This is known as existential unforgeability under adaptive chosen message attack and is the expected security for a digital signature scheme.
  2. Private key privacy after the key generation ceremony. This should protect against an attacker who has access to some (less than threshold t) private key shares.

Below are some attacks we considered and defenses we created for selected threat models.

Server Trust. The centralized server transfers messages between participants.

  • Attack: Unauthorized access to data.
    Defense: All secret data uploaded to the server must be encrypted to the intended participant. The server has no access to private keys, so cannot access data in the messages it relays.
  • Attack: Manipulation of data.
    Defense: Participants validate every piece of data provided by the server, and halt the protocol if they detect data modification.
  • Attack: Data loss.
    Defense: Data from key generation ceremonies are backed up through our disaster-recovery processes (not discussed in detail here) and can be recovered in the case of server data loss.

Participant Trust. Participants hold onto key shares and participate in the signing protocol.

  • Attack: Individual participant performing existential forgery.
    Defense: Participants have the critical responsibility of validating data provided by the server. Any participant can abort the protocol and trigger incident response procedures if malicious activity is detected.
  • Attack: Participants colluding to perform existential forgery.
    Defense: Since any single participant can halt the protocol if they detect malicious activity, the protocol requiring t participants remains secure with up to t — 1 malicious participants. An additional protection against collusion is supporting a hybrid participant model: a combination of humans and servers. We use weighted secret sharing to ensure that every signing requires participation from both human and server participants. This further increases the barrier for compromising t participants.
  • Attack: Nonce Reuse. A well-known attack for Schnorr-style signatures is using the same nonce multiple times on different messages. This leads to a trivial recovery of private keys, compromising our second security goal and opening the door for an immediate loss of funds.
    Defense: Nonce shares encode information about the message, making it simple to detect nonce reuse upon decryption. Having a two-round protocol allows participants to authenticate nonce shares in Round 2 and abort if they detect nonce reuse.

Key Issuer Trust. The key issuer generates private keys and distributes key shares.

  • Attack: Exfiltrating secrets from a key generation ceremony.
    Defense: The process of generating keys is a fully documented and audited process, which requires that all plaintext of keys are destroyed before the culmination of the key generation ceremony.

Through this threat modeling, we see that a malicious entity needs to compromise a threshold of participants to have any chance of stealing funds. We carefully calibrate the human and server participant thresholds with this in mind to ensure that our funds maintain the highest level of security.

Summary

TSS for signing payloads over the Ed25519 curve is an elegant and simple service: it takes as input a message payload and produces a valid signature, after a series of signers interact with the two-round protocol. This service provides a solution for reusing cold keys without bringing them online. Through translating a full cryptographic protocol to a real life service, we created TSS, the first production-level threshold signing service in existence to secure billions of dollars in assets.

Footnotes

  1. More precisely, the public key is used to derive the wallet’s address, which is known to the public.
  2. that are invalid in isolation
  3. The blockchain does not have to be aware of nor support special logic for threshold signatures, since the signature created is the same signature created using the composite private key.
  4. Using the message as associated data for encryption. This ensures that this nonce can only be used for signing this message. This defends against nonce-replay attacks that lead to private key recovery.

Read more about Cryptography at Coinbase.

If you are interested in the complexity of applying threshold cryptography, Coinbase is hiring Cryptographers and Software Engineers.

This website contains links to third-party websites or other content for information purposes only (“Third-Party Sites”). The Third-Party Sites are not under the control of Coinbase, Inc., and its affiliates (“Coinbase”), and Coinbase is not responsible for the content of any Third-Party Site, including without limitation any link contained in a Third-Party Site, or any changes or updates to a Third-Party Site. Coinbase is not responsible for webcasting or any other form of transmission received from any Third-Party Site. Coinbase is providing these links to you only as a convenience, and the inclusion of any link does not imply endorsement, approval or recommendation by Coinbase of the site or any association with its operators.

All images herein are by Coinbase.


Production Threshold Signing Service was originally published in The Coinbase Blog on Medium, where people are continuing the conversation by highlighting and responding to this story.

Coinbase Scores Major Legal Win – SEC Stalled by Rare Court Ruling