Ir al contenido principal

Servicio de Atestación

Cómo configurar, ejecutar y administrar un servicio de Atestación como Validador de Celo.

New update (as of January 2023)

Validators participating in the attestation protocol:

  • may turn off their Attestation Service instances immediately including any full nodes and SMS API subscriptions (i.e. Twilio, Nexmo, and MessageBird) supporting them
  • should remain attestation signers on-chain until Q1 2023 when a governance proposal will be voted on to make the Attestations contract read-only
  • more information on forum post

¿Qué es un Servicio de Attestation?

The Attestation Service is part of the Celo identity protocol. It sends SMS on behalf of users to allow them to attest to having access to a phone number and to map that to a Celo account, securely and privately. This is shown as Steps 3 and 4 in this diagram:

Validators receive a fee (set by on-chain governance, currently 0.05 cUSD) for every attestation that they process and that is then successfully redeemed on-chain by the user. Validators can claim and withdraw this fee using: celocli identity:withdraw-attestation-rewards.


This guide steps you through setting up an Attestation Service:

  • Follow the instructions to set up a validator on mainnet or baklava
  • Configure Twilio, MessageBird and Nexmo, the SMS providers used by Attestation Service
  • Generate and register an attestation signer key
  • (for versions prior to 1.4.0) Deploy a Celo full node, with the attestation signer key unlocked
  • Deploy the attestation service
  • Configure and publish validator metadata so that clients can find your attestation service
  • Configure monitoring for the attestation service and the full node (if applicable)
If you have any questions or feedback after reading the documentation, please feel free to share them with us on GitHub: celo-org > identity > Discussions. We will happily get back to you and :::

Lanzamientos recientes

Arquitectura de despliegue

Attestation Service needs to expose a HTTP or HTTPS endpoint to the public Internet. This means it should not be deployed on the same physical host as a Validator, which should be firewalled to allow incoming connections only from its proxy.

The PORT environment variable sets the listening port for the service on the local instance. Note that depending on your setup, this may be different from the port exposed to the public Internet.

Attestation Service exposes a HTTP endpoint, but it is strongly recommended that you adopt a setup that implements TLS. Attestation Service must expose the following routes to the public Internet: POST /attestations, POST /test_attestations, GET /get_attestations, POST /delivery_status_nexmo, (v1.5.0+) POST /delivery_status_twilioverify, (v1.5.0+) POST /delivery_status_twiliomessaging, (pre-v1.5.0) POST /delivery_status_twilio, and (v1.2.0+) GET (not POST) /delivery_status_messagebird. It should also expose GET /status. Optionally you may choose to expose GET /healthz and GET /metrics. Note that the URL provided in the validator metadata should not include any of these suffixes.

From Attestation Service version 1.4.0 onwards, there are two ways of deploying the Attestation Service. We recommend that new validators use the file keystore method (instead of using a Celo full node) for key management, and that existing validators eventually migrate to the new architecture.

An Attestation Service prior to version 1.4.0 is usually deployed alongside a Celo full node instance, which needs to have the attestation signer key unlocked. This can be either deployed on the same physical machine, or in a VM or container on a different host.

While it is still possible to use the full node method described below, from version 1.4.0 onwards, it is recommended to instead deploy the Attestation Service with access to a keystore file that encrypts the attestation signer key. This allows the service to sign attestations locally instead of depending on the separate full node instance to sign attestations. The passphrase for decrypting the keystore file must be passed in as an environment variable when starting up the Attestation Service. At least one Celo Provider (environment variable CELO_PROVIDERS (recommended) or CELO_PROVIDER) is currently still required, in order to connect to ContractKit and read necessary information from the chain. Listing a couple of providers is recommended, as if the first node is behind or syncing, the Attestation Service will use one of the backup nodes listed. More details on this are in the Running the Attestation Service v1.4.0+ section below. The new method of signing is expected to reduce Attestation Service errors due to the full node not being synced and generally reduce operating overhead.

The Attestation Service is a stateless service that uses a database to persist status of current and recently completed SMS delivery attempts. The most straightforward deployment architecture is to have a single machine or VM running three containers (two for versions 1.4.0 onwards): one the attestation service, a Celo Blockchain node (only for versions prior to 1.4.0), and a single database instance.

For a high availability setup, multiple instances can be deployed behind a load balancer and sharing a single database service. The load balancer should be configured with a round robin routing policy using the instances' /healthz endpoint as a healthcheck. Deploying a high availability database setup is beyond the scope of these instructions, but is straightforward with most cloud providers. In this setup, if a delivery report for an SMS issued by one instance is received by another instance, that instance can identify the matching record in the shared database and act on the receipt to resend if necessary.

Every record in the database includes the issuer (i.e. validator) in its key, so a single setup like the above can be used to provide attestations for multiple validators.

Proveedores de SMS

Currently the Attestation Service supports three SMS providers:

  • Twilio
    • from v1.5.0, the Attestation Service treats the Twilio Messaging Service (twiliomessaging) and the Twilio Verify API (twilioverify) as separate providers.
  • Nexmo
  • MessageBird (from version 1.2.0 and later)

It is recommended that you sign up with all three.

See the Configuration section for information about how to specify configuration options.


After you sign up for Twilio at, you should see your ACCOUNT SID and your AUTH_TOKEN in the top right of the console. You'll also want to enter in a credit card to fund the account. For most text messages, the costs are typically very low (and significantly lower than the attestation fee paid by the user). Find a more comprehensive price list at If there are countries that you do not want to serve, you can specify them with the TWILIO_UNSUPPORTED_REGIONS configuration option.

Next, adjust the Geo settings to serve phone numbers globally under Otherwise, the service will not be able to send SMS to Celo's global user base and your validator will negatively impact the Celo user experience.

To actually be able to send SMS, you need to create a messaging service under Programmable SMS > SMS. Provide the resulting SID in the TWILIO_MESSAGING_SERVICE_SID configuration variable.

Now that you have provisioned your messaging service, you need to buy at least 1 phone number to send SMS from. You can do so under the Numbers option of the messaging service page. It is strongly recommended that you purchase at least a US (+1) number which seem to provide high delivery success rates. If you purchase numbers in other locales, Twilio will intelligently select the best number to send each SMS.

Verificar servicio (post v1.4.0)

We're in the process of transitioning to Twilio's Verify Service which will automatically manage a set of phone numbers for global reach. Create a Verify Service in the Twilio Portal by navigating to Verify and click + to create a new service. It's important to provide Celo as the service friendly name, since this will show up in the text message content.

  1. Establece la longitud del código a 8 dígits.
  2. Introduzca sell-oh en el TTS SERVICE NAME.
  3. Activa SMS, CALLy EMAIL canales de entrega.

After you create the Verify Service, you must create a support ticket to enable the custom code feature. Provide Twilio support your new Verify SID and request enabling the custom code feature. Please monitor for a response and respond to any follow up questions.

Support ticket request template

Hello, I'd like to enable custom codes for our Verify API with SID {YOUR_VERIFY_SID}. I understand that we will be charged on each attempted user verification.

After Twilio enables custom codes, you'll see the following property in the Twilio dashboard when viewing your Verify Service:

Custom Code Property

Once you have confirmation that custom codes are enabled on your Twilio account, you can provide the resulting SID in the TWILIO_VERIFY_SERVICE_SID configuration variable and start the service. Since there are a few countries for which the Messaging Service consistently outperforms the Verify Service (and vice versa), from version v1.5.0 onwards, we treat the Messaging and Verify services as separate SMS providers which can be specified as twiliomessaging and twilioverify, respectively. These providers can be specified on a per-country basis; that is, you could specify the Messaging Service to be used for a particular country by setting SMS_PROVIDERS_X=twiliomessaging,nexmo,.... (Note that twilio will continue to work as shorthand for twiliomessaging,twilioverify, to maintain backwards compatibility.)

For sending messages to the US, we recommend using the Twilio Verify API(provider: twilioverify) as opposed to the Messaging Service in order to comply with 10DLC regulations (this can be specified in the SMS_PROVIDERS_US variable). Otherwise, you may need to register your brand in order to avoid fees.


After signing up for Nexmo, click the balance in the top-left to go to Billing and Payments, where you can add funds. It is strongly recommended that you use a credit or debit card (as opposed to other forms of payment) as you will then be able to enable Auto reload. You should also enable Low balance alerts. Both of these will help avoid failing to deliver SMS when your funds are exhausted. It appears that these options may not be immediately available for all new accounts due to fraud checks: try sending a few SMS, checking back after a few days, or raising a support ticket.

Under Your Numbers, create a US number and ensure that is enabled for SMS; this number will be used to send international text messages. Note that Nexmo numbers appear to have a rate limit of 250 SMS per day. We recommend configuring your Attestation Service to not use Nexmo to serve the US (i.e. remove nexmo in SMS_PROVIDERS_US). If you still want to do so, please configure a US toll-free number according to the guidance here and ensure that your Attestation Service is running at v1.2.2+.

Under Settings, copy the API key into the environment variable NEXMO_KEY, and API secret into NEXMO_SECRET.

If you wish to partition the numbers used within this account, you may choose to create and configure a Nexmo application for each one. In each application, enable messaging (labeled as Communicate with WhatsApp, Facebook Messenger, MMS and Viber) and assign a number. Copy each application's Application Id value into the appropriate instance's NEXMO_APPLICATION configuration value. There is no need to generate or use a public/private keypair. By default an Attestation Service will pick a number from the global pool of numbers not linked to a specific Nexmo application. The only effect of supplying NEXMO_APPLICATION is to select numbers from those linked to that application.

Note that from version 1.2.0, the Attestation Service no longer requires callback URLs to be supplied in the Nexmo dashboard. This means one can support multiple Attestation Services using a single account. However to receive the delivery receipts from Nexmo, it is important to update the default HTTP method in the Nexmo dashboard to POST-JSON (see image below or follow the instructions here), since the Attestation Service currently expects POST requests routed to the /delivery_status_nexmo endpoint.


MessageBird support is introduced in version 1.2.0 and later. After signing up for MessageBird, locate the Your API Keys section on the Dashboard, click Show next to the Live key, and copy its value into the MESSAGEBIRD_API_KEY configuration variable. Click Top Up to add credit. MessageBird requires a dedicated number and/or KYC approval to send SMS to certain countries that validators must support. Click Numbers then Buy Number to purchase a number. You will need to purchase separate numbers for both the USA (see below) and Canada. Then visit SMS Settings and request approval to send to these countries. You can find guidance on filling in the required information here.

Due to 10DLC regulations from 2021, we now recommend setting up a toll-free number to serve US numbers. Please see this page for more guidance on how to request a toll-free number and how to fill out the necessary form. If you do not set up a toll-free number, you must either register your brand according to the instructions here OR remove messagebird from your configuration of SMS_PROVIDERS_US.

Failure to comply with 10DLC regulations in the US can potentially result in fines or blocked traffic.



Where necessary, the instructions will differentiate between pre-v1.4.0 (Celo full node for key management) and v1.4.0+ (recommended use of keystore files for key management). This section uses several environment variables defined during the validator setup. You'll need to export CELO_IMAGE and CELO_VALIDATOR_RG_ADDRESS on this machine.

Setting up an Attestation Service first requires an Attestation Signer key to be registered (Similar to Validator and Vote signer keys). For that let's start our node on the Attestations machine (keep track of the password you use for this account):

# On the Attestation machine
docker run -v $PWD:/root/.celo --rm -it $CELO_IMAGE account new

Let's generate the proof-of-possession for the attestation signer:

# On the Attestation machine
docker run -v $PWD:/root/.celo --rm -it $CELO_IMAGE account proof-of-possession $CELO_ATTESTATION_SIGNER_ADDRESS $CELO_VALIDATOR_RG_ADDRESS

With this proof, authorize the attestation signer on your local machine:

# On your local machine
celocli releasegold:authorize --contract $CELO_VALIDATOR_RG_ADDRESS --role attestation --signature 0x$CELO_ATTESTATION_SIGNER_SIGNATURE --signer $CELO_ATTESTATION_SIGNER_ADDRESS

Configurando Gestión de Claves

(recomendado) v1.4.0+ - Usar Archivos Keystore

It is no longer necessary to run a full node alongside the Attestation Service. Instead, save the path to the keystore directory generated above and the password used when creating the CELO_ATTESTATION_SIGNER_ADDRESS above, as you will need these when running the service:


Then, follow the instructions in the Running the Attestation Service section below.

pre-v1.4.0 - Usar nodo completo de Celo

You can now run the node for the attestation service in the background with the following command. Remember to specify the password you used during the creation of the CELO_ATTESTATION_SIGNER_ADDRESS. And, if you want to run the attestation service for Baklava, add the --baklava flag.

# On the Attestation machine
docker run --name celo-attestations -it --restart always --stop-timeout 300 -p -v $PWD:/root/.celo $CELO_IMAGE --verbosity 3 --syncmode full --http --http.addr --http.api eth,net,web3,debug,admin --unlock $CELO_ATTESTATION_SIGNER_ADDRESS --password /root/.celo/.password --allow-insecure-unlock

Configuración de la Base de Datos

For storing and retrieving the attestation requests the service needs a database to persist that information. Currently sqlite, postgres and mysql are supported. For testing purposes you can use sqlite but it's recommended to run a stand-alone database server using mysql or postgres if your intention is running the Attestation Service in a production environment. If you are running on a popular cloud provider, consider using their hosted SQL services.

Depending on your database technology you need to create a database with the access for a specific user and password.

For specifying the database url you need to setup the DATABASE_URL variable in one of these ways:

# On the Attestation machine
export DATABASE_URL="sqlite://db/attestation.db"
export DATABASE_URL="mysql://"
export DATABASE_URL="postgres://"

Example of setting up a local postgres database on Ubuntu:

apt install postgresql
sudo -u postgres createdb attestation-service
sudo -u postgres psql -c "ALTER USER postgres PASSWORD '<DATABASE_PASSWORD>';"
export DATABASE_URL="postgres://postgres:<DATABASE_PASSWORD>@localhost:5432/attestation-service"


Attestation Service can use its config from a file that can be specified using CONFIG environment variable. We highly recommend that you start by using the template Attestation Service config file, which contains up-to-date, sensible defaults especially for SMS_PROVIDERS_<country>:

# Choose a location for the config and fetch the defaults
export CONFIG=/path/to/attestation-service-config
curl >$CONFIG

Lines beginning # are treated as comments. In addition, any options specified as environment variables override values provided in this file.

Required options:

DATABASE_URLLa URL para acceder a la base de datos local, por ejemplo, sqlite://db/attestations.db
CELO_PROVIDERS(v1.4.0+) Recomendado sobre CELO_PROVIDER; solo uno de los dos puede ser usado. Una lista de URLs de nodos Celo priorizadas utilizadas para conectarse a la cadena. Se recomiendan 2-3 proveedores.
CELO_PROVIDER(requiere pre-v1.4.0; no recomendado v1.4.0+) La URL del nodo local completo en el que se desbloquea la clave del firmante de la verificación. Por ejemplo: http://localhost:8545/. ¡No exponga este puerto a la Internet pública! (v1.4.0+ opcional) URL del nodo Celo utilizado para conectarse a la cadena.
CELO_VALIDATOR_ADDRESSDirección de la cuenta de Validador. Si el validador se despliega a través de un contrato ReleaseGold, esta es la dirección del contrato (por ejemplo, $CELO_VALIDATOR_RG_ADDRESS), no el beneficiario.
ATTESTATION_SIGNER_ADDRESSDirección de la clave de firma de certificado del validador
SMS_PROVIDERSLista separada por comas de todos los proveedores SMS habilitados. Puede incluir twilio, nexmo. Desde la v1.2.0, puede incluir messagebird. Se recomienda listar nexmo último si está configurado. De v1.5.0, puede incluir twiliomessaging y twilioverify en lugar de twilio. Los proveedores son probados de primera a última hora, a menos que SMS_PROVIDERS_RANDOMIZED esté establecido en 1, en cuyo caso son probados en un orden aleatorio.

Optional environment variables:

ATTESTATION_SIGNER_KEYSTORE_DIRPATH(v1.4.0+) Ruta al directorio keystore que contiene la clave privada de ATTESTATION_SIGNER_ADDRESScifrada. Debe utilizarse con ATTESTATION_SIGNER_KEYSTORE_PASSPHRASE.
ATTESTATION_SIGNER_KEYSTORE_PASSPHRASE(v1.4.0+) Contraseña utilizada para cifrar el archivo de almacén de claves de ATTESTATION_SIGNER_ADDRESS. Debe utilizarse con ATTESTATION_SIGNER_KEYSTORE_DIRPATH
PORTPuerto al que escuchar. Por defecto 3000.
RATE_LIMIT_REQS_PER_MIN(v1.2.0+) Solicitudes por minuto en todos los extremos antes de que las nuevas solicitudes sean limitadas. Por defecto 100.
SMS_PROVIDERS_<country>Anular para establecer proveedores SMS y pedir un código de país específico (por ejemplo, SMS_PROVIDERS_MX=nexmo,twilio). Recomendamos encarecidamente usar el default configuration file como base y luego hacer los cambios en consecuencia.
SMS_PROVIDERS_RANDOMIZED(v1.2. +) Si se establece en 1 y no hay proveedores específicos de países configurados para el país del número solicitado, aleatorizar el orden de los proveedores predeterminados. Por defecto 0. Nota: solo se recomienda configurar esto a 1 si no tiene Vonage/Nexmo configurado como un proveedor.
MAX_DELIVERY_ATTEMPTSNúmero total de intentos de entrega al enviar SMS. Cada intento prueba el siguiente proveedor disponible en el orden especificado. Si se omite, se utilizará la opción MAX_PROVIDER_RETRIES desaprobada. El valor por defecto es 3.
MAX_REREQUEST_MINSNúmero de minutos durante los cuales el cliente puede releer la misma certificación. El valor por defecto es 55.
EXTERNAL_CALLBACK_HOSTPORTProporciona la URL externa completa en la que se puede acceder al servicio, usualmente igual que el valor de la reclamación de ATTESTATION_SERVICE_URL en sus metadatas. Este valor, además de un sufijo p. ej. /delivery_status_twilioverify será la URL en la que el servicio puede recibir devoluciones de recibo de entrega. Si este valor no está establecido y VERIFY_CONFIG_ON_STARTUP=1 (el valor por defecto), la URL será tomada de los metadatos del validador. De lo contrario, habrá que suministrarlo.
VERIFY_CONFIG_ON_STARTUPRechazar iniciar si el firmante o los metadatos están mal configurados. Por defecto 1. Si desactiva esto, debe especificar EXTERNAL_CALLBACK_HOSTPORT.
MAX_AGE_LATEST_BLOCK_SECS(v1.2.0+) Edad máxima del último bloque recibido, en segundos, antes del fallo del chequeo de salud. Por defecto es 20.
GET_BLOCK_TIMEOUT_MS(v1.4.0+) Tiempo máximo en milisegundos para esperar después de obtener el último bloque de una conexión, antes de que se agote. Por defecto es 500 ms.
DISABLE_SMART_FALLBACK(v1.4.0+) Si true, no intenta seleccionar el proveedor más actualizado para cada llamada, pero seguirá intentando realizar llamadas fallidas con la(s) copia de seguridad(es). Por defecto es false.
DB_RECORD_EXPIRY_MINSTiempo en minutos antes de que se elimine un registro de un certificado en la base de datos. Por defecto 60 minutos.
LOG_LEVELUno de los fatal, error, warn, info, debug, trace
LOG_FORMATUno de json, human, stackdriver
APP_SIGNATUREUn valor que se muestra bajo el campo clave appSignature en el endpoint /status que se puede utilizar para identificar múltiples instancias.

Twilio configuration options:

TWILIO_ACCOUNT_SIDEl ID de cuenta de Twilio
TWILIO_MESSAGING_SERVICE_SIDEl Twilio Message Service ID. Comienza con MG
TWILIO_VERIFY_SERVICE_SIDEl servicio de verificación Twilio ID. Comienza con VA
TWILIO_AUTH_TOKENEl token de autenticación API
TWILIO_UNSUPPORTED_REGIONSOpcional. Una lista separada por comas de códigos de país para no servir, valor recomendado CU,SY,KP,IR,SD

Nexmo configuration options:

NEXMO_KEYLa clave API de la API Nexmo
NEXMO_SECRETEl secreto de API para la API de Nexmo
NEXMO_APPLICATIONOpcional. Utilice sólo números vinculados a la aplicación Nexmo con ID coincidente, en lugar del grupo global.
NEXMO_UNSUPPORTED_REGIONSOpcional. Una lista separada por comas de códigos de país para no servir, valor recomendado CU,SY,KP,IR,SD
NEXMO_ACCOUNT_BALANCE_METRICOpcional. Deshabilitado por defecto. Si se establece en 1, los balances nexmo se publicarán bajo la métrica attestation_provider_balance.

MessageBird configuration options (v1.2.0+):

MESSAGEBIRD_API_KEYLa clave API para la API de MessageBird
MESSAGEBIRD_UNSUPPORTED_REGIONSOpcional. Una lista separada por comas de códigos de país para no servir, valor recomendado CU,SY,KP,IR,SD

Registrando Metadatos

Celo uses Metadata to allow accounts to make certain claims without having to do so on-chain. Users can use any authorized signer address to make claims on behalf of the registered Account. For convenience this guide uses the CELO_ATTESTATION_SIGNER_ADDRESS, but any authorized signer will work. Note that metadata needs recreating if the key signing it is changed; it is recommended not to use the validator signer address since that key is typically rotated more regularly.

To complete the metadata process, we have to claim which URL users can request attestations from. Run the following commands on your local machine. This section uses several environment variables defined during the validator setup.

# On your local machine
celocli account:create-metadata ./metadata.json --from $CELO_VALIDATOR_RG_ADDRESS

The CELO_ATTESTATION_SERVICE_URL variable stores the URL to access the Attestation Service deployed. In the following command we specify the URL where this Attestation Service is. Note that the URL provided in the validator metadata should be the base path at which the service is accessible; it should NOT include /attestations.

# On your local machine
celocli account:claim-attestation-service-url ./metadata.json --url $CELO_ATTESTATION_SERVICE_URL --from $CELO_ATTESTATION_SIGNER_ADDRESS

You should now host your metadata somewhere reachable via HTTPS. You can use a service like Create a gist with the contents of the file and then click on the Raw button to receive the permalink to the machine-readable file.

Now we can register this url for others to see. To do this, we must have the beneficiary address of the ReleaseGold contract (CELO_VALIDATOR_ADDRESS) unlocked.

(Note: If you used a Ledger to create the beneficiary address, add the --useLedger flag and possibly the --ledgerAddresses=N flag to the below command. The latter flag will have the ledger check N number of addresses, e.g. --ledgerAddresses=5 would have the Ledger check 5 addresses. Don't forget to confirm the transaction on your Ledger after initiating it via the CLI.)

# On your local machine
celocli releasegold:set-account --contract $CELO_VALIDATOR_RG_ADDRESS --property metaURL --value <METADATA_URL>

If everything goes well users should be able to see your claims by running:

# On your local machine
celocli account:get-metadata $CELO_VALIDATOR_RG_ADDRESS

Ejecutando el Servicio de Attestación

There is a slight difference in starting up the service depending on the keystore management option (keystore files, full node) used, and both of these are described below.

Before running the Attestation Service using either method, ensure that the metadata has been registered.

Both of the following options for running the Attestation Service use --network host to access a local database (only works on Linux), and listen for connections on port 80.

They both assume that all of the configuration options needed have been added to the config file located under $CONFIG which Docker will process. Alternatively, you can pass the config file for the service to read on startup using -e CONFIG=<docker-path-to-config-file>, and other environment variables directly by adding arguments of the form -e DATABASE_URL=$DATABASE_URL.

For both options below, set the TAG environment variable to determine which image to install. Use attestation-service-mainnet for the latest image suitable for mainnet (as below), attestation-service-baklava for the latest image suitable for baklava, or specify a specific build as given in the release notes linked above.

(recomendado) Ejecutar el Servicio de Attestation v1.4.0+

The main difference between the old method of running the Attestation Service alongside a Celo full node is that you will need to ensure that Docker can access the directory containing the keystore which stores the CELO_ATTESTATION_SIGNER_ADDRESS's private key as an encrypted file. Here, keystore just means a directory (usually titled "keystore") that contains ONLY keystore files (files that contain the password-encrypted private key in a particular format). This directory and files are automatically created by geth when importing private keys (see Using Keystore Files, and can be used here.

To do this, you need to map the directory containing the keystore to the Attestation Service's Docker volume and set the environment variable ATTESTATION_SIGNER_KEYSTORE_DIRPATH to the path to this directory relative to the Docker container. You will also need to set the environment variable ATTESTATION_SIGNER_KEYSTORE_PASSPHRASE to the password used during the creation of the CELO_ATTESTATION_SIGNER_ADDRESS.

Additionally, ensure that the CELO_PROVIDERS environment variable points to at least one (recommended: 2-3 in total) Celo node that can be used to instantiate ContractKit; this can be a separate full node or, depending on your configuration, your validator proxy node. The CELO_PROVIDERS environment variable is a comma separated value list (ex. CELO_PROVIDERS=, To use your validator proxy node, you would need to allow RPC access, but for security reasons, ensure that this is locked down only to the Attestation Service. Alternatively, provide the endpoint to a Celo node that you run or to a node service provider like Figment Datahub. When passing in multiple providers to this environment variable, prioritize this list by the order in which they should be used to retry failed calls. Unless DISABLE_SMART_FALLBACK is set, the Attestation Service will also attempt to select and use the most up-to-date connection for each call.

The command below illustrates what this could look like, if you used the command docker run -v $PWD:/root/.celo --rm -it $CELO_IMAGE account new from earlier in the instructions above to create the CELO_ATTESTATION_SIGNER_ADDRESS. Recall that you set KEYSTORE_PARENT_DIR to the working directory ($PWD) during the instructions above, and saved the password to the file KEYSTORE_PARENT_DIR/.password. Note that $KEYSTORE_PARENT_DIR/keystore must contain ONLY keystore files (no sub-directories or other file types). Environment variables can be set either in the $CONFIG file or passed into the docker run command directly using the -e flag. (In this example, two of these variables are passed in via the -e flag for clarity.)

export VOLUME_DIRPATH=/root/.celo

# On the Attestation machine
export TAG=attestation-service-mainnet
docker run --name celo-attestation-service -it --restart always --entrypoint /bin/bash --network host --env-file $CONFIG -v $KEYSTORE_PARENT_DIR:$VOLUME_DIRPATH -e PORT=80 -e ATTESTATION_SIGNER_KEYSTORE_PASSPHRASE=$(cat $KEYSTORE_PARENT_DIR/.password) -e ATTESTATION_SIGNER_KEYSTORE_DIRPATH=$VOLUME_DIRPATH -p 80:80$TAG -c " cd /celo-monorepo/packages/attestation-service && yarn run db:migrate && yarn start "

Ejecutar el Servicio de Attestation pre-v1.4.0

First, ensure that your local node is fully synced:

# On the Attestation machine, if using a Celo full node for key management
sudo celocli node:synced --node geth.ipc

Then, start the Attestation Service by running:

# On the Attestation machine
export TAG=attestation-service-mainnet
docker run --name celo-attestation-service -it --restart always --entrypoint /bin/bash --network host --env-file $CONFIG -e PORT=80 -p 80:80$TAG -c " cd /celo-monorepo/packages/attestation-service && yarn run db:migrate && yarn start "

Recibos de entrega

Attestation Services supports delivery receipts so that SMS providers can callback to provide delivery information. This triggers retries as needed, even between providers, and enables delivery success and timing metrics to be logged and made accessible to the client.

There is no configuration necessary to enable Twilio or Nexmo delivery receipts. The Attestation Service uses the URL in the validator metadata, provided that VERIFY_CONFIG_ON_STARTUP is enabled. The URL for callbacks can always be specified with the EXTERNAL_CALLBACK_HOSTPORT configuration option. The service appends /delivery_status_{PROVIDER} (i.e. /delivery_status_twilioverify) on to the URL, and supplies that to the provider through its API.

For MessageBird, provide the callback URL (be sure to include /delivery_status_messagebird) in the MessageBird dashboard's API Settings page.

If you are using a load balancer in front of Attestation Service with a URL based routing configuration, be careful to prevent these routes being filtered.

Prueba de punto final

Attestation Service provides a test endpoint.

You can run the following command reference to test an Attestation Service and send an SMS to yourself:

celocli identity:test-attestation-service --from $CELO_ATTESTATION_SIGNER_ADDRESS --phoneNumber <YOUR-PHONE-NUMBER-E164-FORMAT> --message <YOUR_MESSAGE> [--provider <PROVIDER>]

You need the attestation signer key available and unlocked on your local machine.

You may wish to do this once for each provider you have configured (i.e. --provider=messagebird). If the provider option is not recognized, please upgrade celocli.

For twilio, please note the following to test the SMS vs. verify API from v1.5.0 onwards:

  • --provider=twilioverify (v1.5.0+)
  • --provider=twiliomessaging (v1.5.0+)
  • --provider=twilio (up to v1.4.0)

Note that this does not use an identical code path to real attestations (since those require specific on-chain state) so this endpoint should not be used in place of monitoring logs and metrics.

You should receive an SMS, and the Attestation Service should log messages indicating that the message was Sent and then, if delivery reports can be made successfully, Delivered. Depending on the provider, you may receive several callbacks as the message progresses through the network.

If this works then your attestation service should be successfully deployed!


It is important to monitor the Attestation Service and, if using a full node for key management, also monitor the full node that it depends on.


The Attestation Service provides JSON-format structured logs.

Revisión de salud

The /healthz endpoint will respond with status 200 when all of the following are true: the attestation signer key is available and unlocked, the node is not syncing, the latest block is recent, and the database is accessible. Otherwise it will respond with status 500.

Use this endpoint when configuring a load balancer in front of multiple instances. The results of the last healthcheck are reported via the attestation_service_healthy metric.

Attestation Service also has a /status endpoint for configuration information.


Attestation Service exposes the following Prometheus format metrics at /metrics for attestations made. Please note that metrics are per instance.

Please note that monitoring endpoints including metrics are exposed as a path on the usual host port. This means they are public by default. If you want metrics to be internal only, you will need to configure a load balancer appropriately.

Metrics for the service:

  • attestation_service_healthy: Gauge with value 0 or 1 indicating whether the instance failed or passed its last healthcheck. Calls to /healthz update this gauge, and the process also runs a background healthcheck every minute. It is strongly recommended that you monitor this metric.

Metrics for attestation requests:

  • attestation_requests_total: Counter for the number of attestation requests.

  • attestation_requests_rerequest: Counter for the number of attestation re-requests. A client that rerequests the same attestation is similar to the service receiving a delivery failure notification.

  • attestation_requests_already_sent: Counter for the number of attestation requests that were received but dropped because the local database records that they have already been completed.

  • attestation_requests_wrong_issuer: Counter for the number of attestation requests that were received but dropped because they specified the incorrect validator.

  • attestation_requests_without_incomplete_attestation: Counter for the number of attestation requests that were received but when querying the blockchain no matching incomplete attestation could be found.

  • attestation_requests_valid: Counter for the number of requests received that are for the correct issuer and an incomplete attestation exists.

  • attestation_requests_attestation_errors: Counter for the number of requests for which producing the attestation failed. This could be due to phone number or salt that does not match the hash, or the attestation was recorded fewer than 4 blocks ago.

  • attestation_requests_unable_to_serve: Counters for the number of requests that could not be served because no SMS provider was configured for the phone number in the request. Label country breaks down the count by country code.

  • attestation_requests_number_type: Counter for attestation requests by the type of the phone number. Label country breaks down the counny by country code. Label type has values including: fixed_line, mobile, fixed_line_or_mobile, toll_free, premium_rate, shared_cost, voip, personal_number, pager, uan, voicemail, unknown.

  • attestation_requests_sent_sms: Counter for the number of SMS successfully sent.

  • attestation_requests_failed_to_send_sms: Counter for the number of SMS that failed to send.

  • attestation_requests_believed_delivered_sms: Counter for the number of SMS that were eventually delivered, or believed to be delivered after a timeout without hearing about delivery failure.

  • attestation_requests_unexpected_errors: Counter for the number of unexpected errors.

The following metrics track each delivery attempt. Each client request for an attestation may result in several delivery attempts, at most MAX_DELIVERY_ATTEMPTS configured for that country:

  • attestation_attempts_delivery_status: Counter for delivery attempts made. Label country breaks down the count by country code. Label provider identifies the provider. Label status identifies the outcome:

    • Created: The request was accepted by the provider.

    • Queued: The SMS is buffered or queued, but still in flight.

    • Upstream: The SMS was passed to an upstream carrier.

    • Delivered: A final delivery receipt was received indicating the SMS was succesfully delivered.

  • attestation_attempts_delivery_error_codes: Counter for delivery attempts made. Label country breaks down the count by country code. Label provider identifies the provider. Label code identifies the provider-specific error codes: see Twilio error codes and Nexmo error codes for more details.

Administrative metrics:

  • The attestation_provider_balance tracks the value of the balance of accounts at supported providers. Label provider identifies the provider. This is currently only supported for Nexmo, and is off by default but can be enabled by setting NEXMO_ACCOUNT_BALANCE_METRIC. The metric is populated as a value in the account currency, e.g USD, and only once a successful SMS has been delivered by that provider.

Respuestas de error

Here is a list of the error codes and messages returned by the Attestation Service and what they mean. This can be helpful when looking through raw attestation service logs. In addition to the error codes listed below, the service also returns 500 for Unknown Error.

422, Entidad no procesable

  • Mismatching issuer, I am ${address} - The attestation request references an issuer address that does not match that of the AS that actually received the request.
  • NO_INCOMPLETE_ATTESTATION_FOUND_ERROR / 'No incomplete attestation found' - The Attestations contract has no record that this AS was randomly assigned as an issuer for the given account/identifier pair.
  • ATTESTATION_ERROR / 'Valid attestation could not be provided' - A call to validateAttestationCode in the Attestations contract has failed. This method checks that (1) there is a non-expired incomplete attestation assigned to the issuer whose signature constitutes the given attestation code.
  • 'Invalid securityCodePrefix' - A security code prefix with an incorrect length was provided in the attestation request.
  • 'Invalid smsRetrieverAppSig' - The provided smsRetrieverAppSig does not match the regex '^[\\w+]{5,12}$'
  • 'Attestation can no longer be re-requested' - The user is re-requesting an attestation that the AS thinks was completed too long ago for it to accept the re-request.
  • 'Delivery attempts exceeded' - The AS has attempted to deliver this attestation to the user too many times and will not try again.
  • ErrorMessages.NO_PROVIDER_SETUP / 'No provider was setup for this phone number' - The AS has not setup an SMS provider
  • ErrorMessages.INVALID_SIGNATURE / 'Invalid signature provided' - The signature provided in a AttestationServiceTestRequest was not generated by either the AS's account address or attestation signer address.

404, no encontrado

  • 'Attestation not found' - The attestation the user is attempting to complete could not be found in the AS's database.

403, prohibido

  • 'Security code attempts exceeded' - The user has attempted to complete the attestation with an incorrect security code too many times. The attestation can no longer be completed.
  • 'Invalid security code' - The user has attempted to complete the attestation with an incorrect security code.

401, no autorizado

  • 'Missing authentication' - the authentication header is missing from the request
  • 'Invalid signature' - The authentication header failed signature verification. It should be signed by either the account's DEK or wallet key.


The number of requested and entirely completed attestations is in effect recorded on the blockchain. The values can be seen at Celo Explorer: enter the Validator's address and click the 'Celo Info' tab.

TheCelo tracks global attestation counts and success rates, and shows detailed information about recent attestation attempts.

Tablero del Servicio de Attestation

After your service is up and running, you can monitor its performance using the public Attestation Service Dashboard. Enter your validator address in the top right search bar to view your service's stats. This dashboard can also be useful for troubleshooting various issues that will arise with certain geographic regions or providers.