How to verify the Coinbase price oracle signature?

Viewed 49

Coinbase price oracle is a signed price feed API. https://docs.cloud.coinbase.com/exchange/reference/exchangerestapi_getcoinbasepriceoracle

Does anyone know how to verify the authenticity of the price data by the Coinbase price oracle public key?

The price data JSON I get from the Coinbase price oracle API looks like this,

{
    "messages": [
        "0x000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000621f0ee800000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000a4847d4a00000000000000000000000000000000000000000000000000000000000000006707269636573000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000034254430000000000000000000000000000000000000000000000000000000000",
        "0x000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000621f0ee800000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000b219df400000000000000000000000000000000000000000000000000000000000000006707269636573000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000034554480000000000000000000000000000000000000000000000000000000000"
],
"prices": {
        "BAT": "0.7477895",
        "BTC": "44162.34"
    },
    "signatures": [
       "0xef893d807434364a70faf3dab7f6ba2ef82c74433ae35ac3c4dc60cd1a9b1df467a4d027e5f63676bf12093671504c01a8fb0411415c35c8469332794b949ae7000000000000000000000000000000000000000000000000000000000000001c",

"0x21e231317d30edb6d999702c7be5f4506d6d1d097fe50dadf8abfef3d87e1ad93d7695d0b39bed6e35195accc8b6f4abef7f66f6ca92930edc350beaed3be860000000000000000000000000000000000000000000000000000000000000001b"
],
    "timestamp": "1646202600"
}
1 Answers

So, the JSON above is structured as follows:

  • timestamp: the timestamp of the data (same timestamp is encoded in the messages)
  • prices: unencoded prices in decimal format (same data is encoded in the messages, this data is NOT signed)
  • messages: a number "n" of Ethereum ABI encoded price data messages (for the dump I am looking at, n=13)
  • signatures: a number, the same "n" as above of hex encoded (strings beginning "0x...") signatures

The signatures are the result of signing (using ECDSA) the keccak256 hash of the corresponding message, so signature[i] is ecdsa_sign(keccak256(message[i]), COINBASE_PRIVATE_KEY).

The signature can be checked using web3.accounts.recover function (which performs ECDSA signature recovery) of the Ethereum web3 library in NodeJS like this:

const Web3 = require('web3');
web3 = new Web3();

const signer_check = web3.eth.accounts.recover(
    web3.utils.keccak256(message), 
    signature, 
    false);

The public key for the Coinbase Oracle seems to be 0xfCEAdAFab14d46e20144F48824d0C09B1a03F2BC, so if that matches signer_check, the signature is valid.

There's some simple, but more complete I wrote code to do verify the whole message, as well as a tool to download the current data from the Coinbase API, on Github here: https://github.com/barnabee/coinbase-oracle-verify. Read the comments in the two JavaScript source files for more info.

Related