Vultisigner
, also known as VultiServer
, is a simple TSS server providing Keygen, Keysign, and Reshare services. Use cases for VultiServer include:
- Front-end applications that can't integrate with mobile-tss-lib will use VultiServer as a TSS server.
- Fast Vault: Allows creating a 2/2 vault with one mobile device, with VultiServer as the second party. Users can sign transactions with one device.
- Fast Vault with 2/3: Allows creating a 2/3 vault with two mobile devices and VultiServer as one party. Users can sign transactions with either mobile device without relying on VultiServer to access their crypto assets.
Vultisigner / VultiServer consists of two components:
- API Server: An HTTP server that handles keygen and keysign requests from clients.
- TSS Worker: A service triggered by the API Server to perform the actual TSS operations.
/ping
, it provide a simple health check for the Api Server , the return value is Vultisigner is running
POST
/vault/create
{
"name": "My Vault",
"session_id": "session id for key generation",
"hex_encryption_key": "hex encoded encryption key",
"hex_chain_code": "hex encoded chain code",
"local_party_id": "local party id",
"encryption_password": "password to encryption the generated vault share",
"email": "email of the user"
}
- name: Vault name
- session_id: Key generation session ID (random UUID)
- hex_chain_code: 32-byte hex encoded string
- hex_encryption_key: 32-byte hex encoded string for encryption/decryption
- local_party_id: Identifier for VultiServer in the keygen session
- encryption_password: Password to encrypt the vault share
- email: Email to send the encrypted vault share
Status Code: OK
POST
/vault/sign
, it is used to sign a transaction
{
"public_key": "ECDSA public key of the vault",
"messages": [
"hex encoded message 1",
"hex encoded message 2",
"hex encoded message N"
],
"session": "session id for this key sign",
"hex_encryption_key": "hex encoded encryption key",
"derive_path": "derive path for the key sign",
"is_ecdsa": "is the key sign ECDSA or not",
"vault_password": "password to decrypt the vault share"
}
- public_key: ECDSA public key of the vault
- messages: Hex encoded messages to be signed
- session_id: Key sign session ID (random UUID)
- hex_encryption_key: 32-byte hex encoded string for encryption/decryption
- derive_path: Derive path for the key sign (e.g., BITCOIN: m/44'/0'/0'/0/0)
- is_ecdsa: Boolean indicating if the key sign is for ECDSA
- vault_password: Password to decrypt the vault share
GET
/vault/get/{publicKeyECDSA}
, this endpoint allow user to get the vault information
Note: please set x-password
header with the password to decrypt the vault share , if the password is empty or incorrect, server will return an error
{
"name": "vault name",
"public_key_ecdsa": "ECDSA public key of the vault",
"public_key_eddsa": "EdDSA public key of the vault",
"hex_chain_code": "hex encoded chain code",
"local_party_id": "local party id"
}
POST
/vault/reshare
, this endpoint allow user to reshare the vault share
{
"name": "My Vault",
"public_key": "ECDSA public key of the vault",
"session_id": "session id for key generation",
"hex_encryption_key": "hex encoded encryption key",
"hex_chain_code": "hex encoded chain code",
"local_party_id": "local party id",
"old_parties": ["old party id 1", "old party id 2"],
"encryption_password": "password to encryption the generated vault share",
"email": "email of the user",
"old_reshare_prefix":"old reshare prefix"
}
- name: Vault name
- public_key: ECDSA public key
- session_id: Reshare session ID (random UUID)
- hex_encryption_key: 32-byte hex encoded string for encryption/decryption
- hex_chain_code: 32-byte hex encoded string
- local_party_id: Identifier for VultiServer in the reshare session
- old_parties: List of old party IDs
- encryption_password: Password to encrypt the vault share
- email: Email to send the encrypted vault share
POST
/vault/resend
, this endpoint allow user to resend the vault share and verification code
Note: user can only request a resend every three minutes
{
"public_key_ecdsa": "ECDSA public key of the vault",
"password": "password to decrypt the vault share",
"email": "email of the user"
}
GET
/vault/verify/:public_key_ecdsa/:code
, this endpoint allow user to verify the code
if server return http status code 200, it means the code is valid , other status code means the code is invalid
- Go 1.21 or higher
- Docker and Docker Compose
- MinIO client (mc)
First, start the required infrastructure services using Docker Compose:
docker compose up -d --remove-orphans
Set up MinIO buckets and access:
mc alias set local http://localhost:9000 minioadmin minioadmin
mc mb local/vultiserver
mc mb local/vultiplugin
You can verify the buckets were created by visiting the MinIO Console:
- URL: http://localhost:9001
- Username: minioadmin
- Password: minioadmin
mkdir -p /tmp/vultisigner/server/vaults
mkdir -p /tmp/vultisigner/plugin/vaults
sudo chmod 777 /tmp/vultisigner/server/vaults
sudo chmod 777 /tmp/vultisigner/plugin/vaults
Start the services in the following order, each one in a different terminal:
export VS_CONFIG_NAME=config-server
go run cmd/vultisigner/main.go
export VS_CONFIG_NAME=config-plugin
go run cmd/vultisigner/main.go
export VS_CONFIG_NAME=config-server
go run cmd/worker/main.go
export VS_CONFIG_NAME=config-plugin
go run cmd/worker/main.go
On a 5th terminal, run :
curl -X POST http://localhost:8081/vault/create \
-H "Content-Type: application/json" \
-d '{
"name": "Server2Server-Vault",
"session_id": "650e8400-e29b-41d4-a716-446655440000",
"hex_encryption_key": "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef",
"hex_chain_code": "2023456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef",
"local_party_id": "2",
"encryption_password": "your-secure-password",
"email": "[email protected]",
"start_session": true,
"parties": ["1", "2"]
}'
Then
curl -X POST http://localhost:8080/vault/create \
-H "Content-Type: application/json" \
-d '{
"name": "Server2Server-Vault",
"session_id": "650e8400-e29b-41d4-a716-446655440000",
"hex_encryption_key": "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef",
"hex_chain_code": "2023456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef",
"local_party_id": "1",
"encryption_password": "your-secure-password",
"email": "[email protected]",
"start_session": false
}'
Once keyGen is done, you can start keysign. You have to replace the ecdsa key by the one appearing in the logs of the keygen.
curl -X POST http://localhost:8081/vault/sign \
-H "Content-Type: application/json" \
-d @- << 'EOF'
{
"public_key": "03b015e2ae364d8f6fff7f2b9fe1760a91e2d41c4a8e91c8750827cea4c3204e5d",
"messages": ["68656c6c6f"],
"session": "650e8400-e29b-41d4-a716-446655440000",
"hex_encryption_key": "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef",
"derive_path": "m/44'/0'/0'/0/0",
"is_ecdsa": true,
"vault_password": "your-secure-password"
}
EOF
Then
curl -X POST http://localhost:8080/vault/sign \
-H "Content-Type: application/json" \
-d @- << 'EOF'
{
"public_key": "03b015e2ae364d8f6fff7f2b9fe1760a91e2d41c4a8e91c8750827cea4c3204e5d",
"messages": ["68656c6c6f"],
"session": "650e8400-e29b-41d4-a716-446655440000",
"hex_encryption_key": "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef",
"derive_path": "m/44'/0'/0'/0/0",
"is_ecdsa": true,
"vault_password": "your-secure-password"
}
EOF
docker compose down
docker compose up -d --remove-orphans
Restart all in order :
# Start servers
export VS_CONFIG_NAME=config-server
go run cmd/vultisigner/main.go
export VS_CONFIG_NAME=config-plugin
go run cmd/vultisigner/main.go
# Start workers
export VS_CONFIG_NAME=config-server
go run cmd/worker/main.go
export VS_CONFIG_NAME=config-plugin
go run cmd/worker/main.go
To verify everything is running correctly:
- Check Docker containers:
docker ps
- Verify MinIO buckets:
mc ls local