Skip to main content
There are two risk control mechanisms for server co-signers: Embedded risk control and TSS Node callback. This guide introduces the security best practices for implementing these two mechanisms.
  • Embedded risk control provides basic, predefined rules that cannot be customized. You configure risk control rules in the configs/cobo-tss-node-config.yaml file.
  • For TSS Node callback, you implement custom risk control logic in your callback server to check callback requests against your specific rules. Key fields to check in the callback request:
    • request_detail: Contains critical information about key generation, key resharing, and transaction signing.
    • extra_info: Provides additional context; should be cross-referenced with request_detail for validation.

Key generation

We recommend using embedded risk control for key generation requests. Callback server logic is usually not needed for this operation. Configure embedded risk control for key generation like this:
embedded_risk_control_rules:
  enable: true
  key_gen:
    reject_all: false
    allow_list:
      - threshold: 2
        node_ids:
          - <Cobo TSS Node ID>
          - <ThirdParty TSS Node ID>
          - <Customer TSS Node ID>
  key_sign:
    reject_all: true
  key_reshare:
    reject_all: true
  key_share_sign:
    reject_all: true
This configuration:
  • Allows key generation with specified threshold and TSS Node IDs
  • Rejects all other requests

Key resharing

We recommend using embedded risk control for key resharing requests. Callback server logic is usually not needed for this operation. Configure embedded risk control for key resharing like this:
embedded_risk_control_rules:
  enable: true
  key_gen:
    reject_all: true
  key_sign:
    reject_all: true
  key_reshare:
    reject_all: false
    allow_list:
      - xpubkey: <EXTENDED_ROOT_PUBKEY>
        new_threshold: 2
        new_node_ids:
          - <Cobo TSS Node ID>
          - <ThirdParty TSS Node ID>
          - <Customer TSS Node ID>
  key_share_sign:
    reject_all: true
This configuration:
  • Allows key resharing requests from a specified key share holder group, threshold, and TSS Node IDs.
  • Rejects all other requests

Transaction signing

We recommend using both embedded risk control and callback server logic for transaction signing requests.

Embedded risk control

Configure your embedded risk control rules for transaction signing:
embedded_risk_control_rules:
  enable: true
  key_gen:
    reject_all: true
  key_sign:
    reject_all: false
  key_reshare:
    reject_all: true
  key_share_sign:
    reject_all: true
This configuration allows only signing requests while rejecting all other requests.

Callback risk control

Implement these security checks in your TSS Node callback server:
  1. Verify the transaction hash to prevent transaction tampering:
    1. Extract the raw transaction data from extra_info.Transaction.RawTxInfo.UnsignedRawTx
    2. Calculate the hash of this raw transaction data according to the rules of the specific chain
    3. Compare the calculated hash with the value in request_detail.msg_hash_list
    4. Reject the transaction if the hashes don’t match
  2. Validate critical transaction parameters to prevent unauthorized or malicious transactions
    1. Parse extra_info.Transaction.RawTxInfo.UnsignedRawTx according to the chain format, and extract key transaction parameters such as:
      • Gas fee: Ensure it is within acceptable ranges
      • Destination address: Verify against allowed addresses
      • Transaction amount: Check against configured limits
      • Chain ID: Confirm it matches your expected network
      • Call data
      • Other specific parameters as needed
    2. Compare the parsed parameters with those in extra_info.Transaction
    3. Compare the parsed parameters or extra_info.Transaction with the original transaction created using the WaaS 2.0 API
Additional information to verify (not security-critical):
  • Validate the signing key share:
    • tweak_list: The list of tweaks to apply.
    • bip32_path_list: BIP32 derivation paths.
    • root_pub_key: Root extended public key of the key share holder group.
    Use these to derive the address or public key of the signing key, ensuring correctness. An incorrect key could lead to withdrawals from unintended addresses.
  • Check signature_type compatibility with the target blockchain, as signature types vary across chains.

Auto-sweeping implementation

For MPC Wallets with auto-sweeping enabled, implement a whitelist-based approval system that:
  1. Verifies the transaction hash to ensure transaction integrity.
  2. Checks if the destination address is on the pre-approved whitelist.
  3. Automatically approves transactions that meet both criteria.
The TSS Node callback server template provides a sample implementation of this whitelisting logic:
  1. Configure the whitelist of destination addresses in callback-server-config.yaml.
  2. Refer to sign.go for examples of:
    • Parsing transaction content
    • Verifying hash against the signed message
    • Approving transactions based on the whitelist
Future updates will expand the sample project to support additional blockchain networks. You can also extend support to more tokens using the token_adapter module in the repository.
Feel free to share your feedback to improve our documentation!