synor/sdk/go/privacy/privacy.go
Gulshan Yadav e65ea40af2 feat: implement Privacy and Contract SDKs for all 12 languages (Phase 5)
Privacy SDK features:
- Confidential transactions with Pedersen commitments
- Bulletproof range proofs for value validation
- Ring signatures for anonymous signing with key images
- Stealth addresses for unlinkable payments
- Blinding factor generation and value operations

Contract SDK features:
- Smart contract deployment (standard and CREATE2)
- Call (view/pure) and Send (state-changing) operations
- Event log filtering, subscription, and decoding
- ABI encoding/decoding utilities
- Gas estimation and contract verification
- Multicall for batched operations
- Storage slot reading

Languages implemented:
- JavaScript/TypeScript
- Python (async with httpx)
- Go
- Rust (async with reqwest/tokio)
- Java (async with OkHttp)
- Kotlin (coroutines with Ktor)
- Swift (async/await with URLSession)
- Flutter/Dart
- C (header-only interface)
- C++ (header-only with std::future)
- C#/.NET (async with HttpClient)
- Ruby (Faraday HTTP client)

All SDKs follow consistent patterns:
- Configuration with API key, endpoint, timeout, retries
- Custom exception types with error codes
- Retry logic with exponential backoff
- Health check endpoints
- Closed state management
2026-01-28 09:03:34 +05:30

682 lines
19 KiB
Go

// Package privacy provides privacy-enhancing cryptographic features.
package privacy
import (
"bytes"
"context"
"encoding/json"
"fmt"
"io"
"net/http"
"sync/atomic"
"time"
)
const DefaultEndpoint = "https://privacy.synor.cc/api/v1"
// Config is the privacy client configuration.
type Config struct {
APIKey string
Endpoint string
Timeout time.Duration
Retries int
Debug bool
}
// KeyType represents the type of cryptographic key.
type KeyType string
const (
KeyTypeEd25519 KeyType = "ed25519"
KeyTypeSecp256k1 KeyType = "secp256k1"
)
// GeneratorType represents the generator used for commitments.
type GeneratorType string
const (
GeneratorDefault GeneratorType = "default"
GeneratorAlternate GeneratorType = "alternate"
)
// PublicKey represents a public key.
type PublicKey struct {
Key string `json:"key"`
Type KeyType `json:"type"`
}
// PrivateKey represents a private key.
type PrivateKey struct {
Key string `json:"key"`
Type KeyType `json:"type"`
}
// ConfidentialUTXO is a UTXO for confidential transactions.
type ConfidentialUTXO struct {
TxID string `json:"txid"`
Vout int `json:"vout"`
Commitment string `json:"commitment"`
RangeProof string `json:"rangeProof"`
Blinding string `json:"blinding,omitempty"`
Amount string `json:"amount,omitempty"`
}
// ConfidentialOutput is an output for confidential transactions.
type ConfidentialOutput struct {
Recipient string `json:"recipient"`
Amount string `json:"amount"`
Blinding string `json:"blinding,omitempty"`
}
// OutputFeatures contains output feature flags.
type OutputFeatures struct {
Flags int `json:"flags"`
LockHeight int `json:"lockHeight,omitempty"`
}
// ConfidentialTxInput is a confidential transaction input.
type ConfidentialTxInput struct {
OutputRef string `json:"outputRef"`
Commitment string `json:"commitment"`
}
// ConfidentialTxOutput is a confidential transaction output.
type ConfidentialTxOutput struct {
Commitment string `json:"commitment"`
RangeProof string `json:"rangeProof"`
Features OutputFeatures `json:"features"`
}
// TransactionKernel is the kernel for confidential transactions.
type TransactionKernel struct {
Features int `json:"features"`
Fee string `json:"fee"`
LockHeight int `json:"lockHeight"`
Excess string `json:"excess"`
ExcessSignature string `json:"excessSignature"`
}
// ConfidentialTransaction is a confidential transaction.
type ConfidentialTransaction struct {
TxID string `json:"txid"`
Version int `json:"version"`
Inputs []ConfidentialTxInput `json:"inputs"`
Outputs []ConfidentialTxOutput `json:"outputs"`
Kernel TransactionKernel `json:"kernel"`
Offset string `json:"offset"`
Raw string `json:"raw"`
}
// VerifyConfidentialTxDetails contains verification details.
type VerifyConfidentialTxDetails struct {
CommitmentsBalance bool `json:"commitmentsBalance"`
RangeProofsValid bool `json:"rangeProofsValid"`
SignatureValid bool `json:"signatureValid"`
NoDuplicateInputs bool `json:"noDuplicateInputs"`
}
// VerifyConfidentialTxResult is the result of verifying a confidential transaction.
type VerifyConfidentialTxResult struct {
Valid bool `json:"valid"`
Details VerifyConfidentialTxDetails `json:"details"`
Error string `json:"error,omitempty"`
}
// RingSignatureComponents contains the signature components.
type RingSignatureComponents struct {
C []string `json:"c"`
R []string `json:"r"`
}
// RingSignature is a ring signature.
type RingSignature struct {
ID string `json:"id"`
MessageHash string `json:"messageHash"`
Ring []string `json:"ring"`
KeyImage string `json:"keyImage"`
Signature RingSignatureComponents `json:"signature"`
RingSize int `json:"ringSize"`
}
// VerifyRingSignatureResult is the result of verifying a ring signature.
type VerifyRingSignatureResult struct {
Valid bool `json:"valid"`
KeyImage string `json:"keyImage"`
}
// StealthAddress is a stealth address.
type StealthAddress struct {
Address string `json:"address"`
ScanPublicKey string `json:"scanPublicKey"`
SpendPublicKey string `json:"spendPublicKey"`
}
// StealthKeypair is a stealth address keypair.
type StealthKeypair struct {
Address StealthAddress `json:"address"`
ScanPrivateKey string `json:"scanPrivateKey"`
SpendPrivateKey string `json:"spendPrivateKey"`
}
// OneTimeAddress is a one-time address derived from a stealth address.
type OneTimeAddress struct {
Address string `json:"address"`
EphemeralPublicKey string `json:"ephemeralPublicKey"`
SharedSecret string `json:"sharedSecret,omitempty"`
}
// SharedSecret is the result of deriving a shared secret.
type SharedSecret struct {
Secret string `json:"secret"`
OneTimePrivateKey string `json:"oneTimePrivateKey"`
OneTimeAddress string `json:"oneTimeAddress"`
}
// Commitment is a Pedersen commitment.
type Commitment struct {
Commitment string `json:"commitment"`
Generator GeneratorType `json:"generator"`
}
// CommitmentWithBlinding is a commitment with its blinding factor.
type CommitmentWithBlinding struct {
Commitment Commitment `json:"commitment"`
Blinding string `json:"blinding"`
}
// RangeProof is a Bulletproof range proof.
type RangeProof struct {
Proof string `json:"proof"`
Commitment string `json:"commitment"`
BitLength int `json:"bitLength"`
}
// VerifyRangeProofResult is the result of verifying a range proof.
type VerifyRangeProofResult struct {
Valid bool `json:"valid"`
MinValue string `json:"minValue"`
MaxValue string `json:"maxValue"`
}
// Error is a privacy error.
type Error struct {
Message string
Code string
StatusCode int
}
func (e *Error) Error() string {
return e.Message
}
// Client is a Synor Privacy client.
type Client struct {
config Config
httpClient *http.Client
closed atomic.Bool
}
// NewClient creates a new privacy client.
func NewClient(config Config) *Client {
if config.Endpoint == "" {
config.Endpoint = DefaultEndpoint
}
if config.Timeout == 0 {
config.Timeout = 30 * time.Second
}
if config.Retries == 0 {
config.Retries = 3
}
return &Client{
config: config,
httpClient: &http.Client{
Timeout: config.Timeout,
},
}
}
// ==================== Confidential Transactions ====================
// CreateConfidentialTxOptions are options for creating a confidential transaction.
type CreateConfidentialTxOptions struct {
Inputs []ConfidentialUTXO
Outputs []ConfidentialOutput
Fee string
LockHeight int
}
// CreateConfidentialTransaction creates a confidential transaction.
func (c *Client) CreateConfidentialTransaction(ctx context.Context, opts CreateConfidentialTxOptions) (*ConfidentialTransaction, error) {
body := map[string]interface{}{
"inputs": opts.Inputs,
"outputs": opts.Outputs,
}
if opts.Fee != "" {
body["fee"] = opts.Fee
}
if opts.LockHeight > 0 {
body["lockHeight"] = opts.LockHeight
}
var resp struct {
Transaction ConfidentialTransaction `json:"transaction"`
}
if err := c.request(ctx, "POST", "/transactions/confidential", body, &resp); err != nil {
return nil, err
}
return &resp.Transaction, nil
}
// VerifyConfidentialTransaction verifies a confidential transaction.
func (c *Client) VerifyConfidentialTransaction(ctx context.Context, tx *ConfidentialTransaction) (*VerifyConfidentialTxResult, error) {
body := map[string]interface{}{
"transaction": tx.Raw,
}
var result VerifyConfidentialTxResult
if err := c.request(ctx, "POST", "/transactions/confidential/verify", body, &result); err != nil {
return nil, err
}
return &result, nil
}
// DecodeConfidentialOutput decodes a confidential output.
func (c *Client) DecodeConfidentialOutput(ctx context.Context, commitment, blinding string) (string, error) {
body := map[string]interface{}{
"commitment": commitment,
"blinding": blinding,
}
var resp struct {
Amount string `json:"amount"`
}
if err := c.request(ctx, "POST", "/transactions/confidential/decode", body, &resp); err != nil {
return "", err
}
return resp.Amount, nil
}
// ==================== Ring Signatures ====================
// CreateRingSignatureOptions are options for creating a ring signature.
type CreateRingSignatureOptions struct {
Message string
Ring []string
PrivateKey string
SignerIndex *int
}
// CreateRingSignature creates a ring signature.
func (c *Client) CreateRingSignature(ctx context.Context, opts CreateRingSignatureOptions) (*RingSignature, error) {
body := map[string]interface{}{
"message": opts.Message,
"ring": opts.Ring,
"privateKey": opts.PrivateKey,
}
if opts.SignerIndex != nil {
body["signerIndex"] = *opts.SignerIndex
}
var resp struct {
Signature RingSignature `json:"signature"`
}
if err := c.request(ctx, "POST", "/ring-signatures/create", body, &resp); err != nil {
return nil, err
}
return &resp.Signature, nil
}
// VerifyRingSignature verifies a ring signature.
func (c *Client) VerifyRingSignature(ctx context.Context, signature *RingSignature, message string) (*VerifyRingSignatureResult, error) {
body := map[string]interface{}{
"signature": signature,
"message": message,
}
var result VerifyRingSignatureResult
if err := c.request(ctx, "POST", "/ring-signatures/verify", body, &result); err != nil {
return nil, err
}
return &result, nil
}
// IsKeyImageUsed checks if a key image has been used.
func (c *Client) IsKeyImageUsed(ctx context.Context, keyImage string) (bool, error) {
var resp struct {
Used bool `json:"used"`
}
if err := c.request(ctx, "GET", fmt.Sprintf("/ring-signatures/key-images/%s", keyImage), nil, &resp); err != nil {
return false, err
}
return resp.Used, nil
}
// GenerateRandomRing generates a random ring of public keys.
func (c *Client) GenerateRandomRing(ctx context.Context, size int, exclude []string) ([]string, error) {
body := map[string]interface{}{
"size": size,
}
if len(exclude) > 0 {
body["exclude"] = exclude
}
var resp struct {
Ring []string `json:"ring"`
}
if err := c.request(ctx, "POST", "/ring-signatures/random-ring", body, &resp); err != nil {
return nil, err
}
return resp.Ring, nil
}
// ==================== Stealth Addresses ====================
// GenerateStealthKeypair generates a new stealth address keypair.
func (c *Client) GenerateStealthKeypair(ctx context.Context) (*StealthKeypair, error) {
var resp struct {
Keypair StealthKeypair `json:"keypair"`
}
if err := c.request(ctx, "POST", "/stealth/generate", nil, &resp); err != nil {
return nil, err
}
return &resp.Keypair, nil
}
// CreateOneTimeAddress creates a one-time address for a stealth address.
func (c *Client) CreateOneTimeAddress(ctx context.Context, stealthAddress *StealthAddress) (*OneTimeAddress, error) {
body := map[string]interface{}{
"scanPublicKey": stealthAddress.ScanPublicKey,
"spendPublicKey": stealthAddress.SpendPublicKey,
}
var resp struct {
OneTimeAddress OneTimeAddress `json:"oneTimeAddress"`
}
if err := c.request(ctx, "POST", "/stealth/one-time-address", body, &resp); err != nil {
return nil, err
}
return &resp.OneTimeAddress, nil
}
// DeriveSharedSecret derives the shared secret for a stealth payment.
func (c *Client) DeriveSharedSecret(ctx context.Context, stealthAddress *StealthAddress, privateKey, ephemeralPublicKey string) (*SharedSecret, error) {
body := map[string]interface{}{
"scanPublicKey": stealthAddress.ScanPublicKey,
"spendPublicKey": stealthAddress.SpendPublicKey,
"privateKey": privateKey,
"ephemeralPublicKey": ephemeralPublicKey,
}
var secret SharedSecret
if err := c.request(ctx, "POST", "/stealth/derive-secret", body, &secret); err != nil {
return nil, err
}
return &secret, nil
}
// ScanForPayments scans transactions for stealth payments.
func (c *Client) ScanForPayments(ctx context.Context, scanPrivateKey, spendPublicKey string, transactions []string) ([]OneTimeAddress, error) {
body := map[string]interface{}{
"scanPrivateKey": scanPrivateKey,
"spendPublicKey": spendPublicKey,
"transactions": transactions,
}
var resp struct {
Payments []OneTimeAddress `json:"payments"`
}
if err := c.request(ctx, "POST", "/stealth/scan", body, &resp); err != nil {
return nil, err
}
return resp.Payments, nil
}
// ==================== Commitments ====================
// CreateCommitment creates a Pedersen commitment.
func (c *Client) CreateCommitment(ctx context.Context, value string, blinding string) (*CommitmentWithBlinding, error) {
body := map[string]interface{}{
"value": value,
}
if blinding != "" {
body["blinding"] = blinding
}
var result CommitmentWithBlinding
if err := c.request(ctx, "POST", "/commitments/create", body, &result); err != nil {
return nil, err
}
return &result, nil
}
// OpenCommitment verifies a Pedersen commitment.
func (c *Client) OpenCommitment(ctx context.Context, commitment, value, blinding string) (bool, error) {
body := map[string]interface{}{
"commitment": commitment,
"value": value,
"blinding": blinding,
}
var resp struct {
Valid bool `json:"valid"`
}
if err := c.request(ctx, "POST", "/commitments/open", body, &resp); err != nil {
return false, err
}
return resp.Valid, nil
}
// AddCommitments adds two commitments.
func (c *Client) AddCommitments(ctx context.Context, commitment1, commitment2 string) (string, error) {
body := map[string]interface{}{
"commitment1": commitment1,
"commitment2": commitment2,
}
var resp struct {
Commitment string `json:"commitment"`
}
if err := c.request(ctx, "POST", "/commitments/add", body, &resp); err != nil {
return "", err
}
return resp.Commitment, nil
}
// SubtractCommitments subtracts two commitments.
func (c *Client) SubtractCommitments(ctx context.Context, commitment1, commitment2 string) (string, error) {
body := map[string]interface{}{
"commitment1": commitment1,
"commitment2": commitment2,
}
var resp struct {
Commitment string `json:"commitment"`
}
if err := c.request(ctx, "POST", "/commitments/subtract", body, &resp); err != nil {
return "", err
}
return resp.Commitment, nil
}
// ComputeBlindingSum computes the sum of blinding factors.
func (c *Client) ComputeBlindingSum(ctx context.Context, positive, negative []string) (string, error) {
body := map[string]interface{}{
"positive": positive,
"negative": negative,
}
var resp struct {
Sum string `json:"sum"`
}
if err := c.request(ctx, "POST", "/commitments/blinding-sum", body, &resp); err != nil {
return "", err
}
return resp.Sum, nil
}
// GenerateBlinding generates a random blinding factor.
func (c *Client) GenerateBlinding(ctx context.Context) (string, error) {
var resp struct {
Blinding string `json:"blinding"`
}
if err := c.request(ctx, "POST", "/commitments/random-blinding", nil, &resp); err != nil {
return "", err
}
return resp.Blinding, nil
}
// ==================== Range Proofs ====================
// CreateRangeProofOptions are options for creating a range proof.
type CreateRangeProofOptions struct {
Value string
Blinding string
Message string
BitLength int
}
// CreateRangeProof creates a Bulletproof range proof.
func (c *Client) CreateRangeProof(ctx context.Context, opts CreateRangeProofOptions) (*RangeProof, error) {
body := map[string]interface{}{
"value": opts.Value,
"blinding": opts.Blinding,
}
if opts.Message != "" {
body["message"] = opts.Message
}
if opts.BitLength > 0 {
body["bitLength"] = opts.BitLength
} else {
body["bitLength"] = 64
}
var resp struct {
Proof RangeProof `json:"proof"`
}
if err := c.request(ctx, "POST", "/range-proofs/create", body, &resp); err != nil {
return nil, err
}
return &resp.Proof, nil
}
// VerifyRangeProof verifies a Bulletproof range proof.
func (c *Client) VerifyRangeProof(ctx context.Context, commitment, proof string) (*VerifyRangeProofResult, error) {
body := map[string]interface{}{
"commitment": commitment,
"proof": proof,
}
var result VerifyRangeProofResult
if err := c.request(ctx, "POST", "/range-proofs/verify", body, &result); err != nil {
return nil, err
}
return &result, nil
}
// CreateAggregatedRangeProof creates an aggregated range proof.
func (c *Client) CreateAggregatedRangeProof(ctx context.Context, outputs []map[string]string) (string, error) {
body := map[string]interface{}{
"outputs": outputs,
}
var resp struct {
Proof string `json:"proof"`
}
if err := c.request(ctx, "POST", "/range-proofs/aggregate", body, &resp); err != nil {
return "", err
}
return resp.Proof, nil
}
// ==================== Lifecycle ====================
// HealthCheck checks if the service is healthy.
func (c *Client) HealthCheck(ctx context.Context) bool {
var resp struct {
Status string `json:"status"`
}
if err := c.request(ctx, "GET", "/health", nil, &resp); err != nil {
return false
}
return resp.Status == "healthy"
}
// Close closes the client.
func (c *Client) Close() {
c.closed.Store(true)
}
// IsClosed returns whether the client is closed.
func (c *Client) IsClosed() bool {
return c.closed.Load()
}
// ==================== Private ====================
func (c *Client) request(ctx context.Context, method, path string, body interface{}, result interface{}) error {
if c.closed.Load() {
return &Error{Message: "client has been closed"}
}
var lastErr error
for attempt := 0; attempt < c.config.Retries; attempt++ {
err := c.doRequest(ctx, method, path, body, result)
if err == nil {
return nil
}
lastErr = err
if attempt < c.config.Retries-1 {
time.Sleep(time.Duration(1<<attempt) * time.Second)
}
}
return lastErr
}
func (c *Client) doRequest(ctx context.Context, method, path string, body interface{}, result interface{}) error {
url := c.config.Endpoint + path
var bodyReader io.Reader
if body != nil {
jsonBody, err := json.Marshal(body)
if err != nil {
return &Error{Message: fmt.Sprintf("failed to marshal body: %v", err)}
}
bodyReader = bytes.NewReader(jsonBody)
}
req, err := http.NewRequestWithContext(ctx, method, url, bodyReader)
if err != nil {
return &Error{Message: fmt.Sprintf("failed to create request: %v", err)}
}
req.Header.Set("Authorization", "Bearer "+c.config.APIKey)
req.Header.Set("Content-Type", "application/json")
req.Header.Set("X-SDK-Version", "go/0.1.0")
resp, err := c.httpClient.Do(req)
if err != nil {
return &Error{Message: fmt.Sprintf("request failed: %v", err)}
}
defer resp.Body.Close()
respBody, err := io.ReadAll(resp.Body)
if err != nil {
return &Error{Message: fmt.Sprintf("failed to read response: %v", err)}
}
if resp.StatusCode >= 400 {
var errResp struct {
Message string `json:"message"`
Error string `json:"error"`
Code string `json:"code"`
}
json.Unmarshal(respBody, &errResp)
msg := errResp.Message
if msg == "" {
msg = errResp.Error
}
if msg == "" {
msg = fmt.Sprintf("HTTP %d", resp.StatusCode)
}
return &Error{
Message: msg,
Code: errResp.Code,
StatusCode: resp.StatusCode,
}
}
if result != nil {
if err := json.Unmarshal(respBody, result); err != nil {
return &Error{Message: fmt.Sprintf("failed to parse response: %v", err)}
}
}
return nil
}