service

package
v0.9.0-pre2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 8, 2021 License: MIT Imports: 35 Imported by: 0

README

Wallet API

This package provides the basic cryptography to sign Vega transactions, and a basic key management system: wallet service. It can be run alongside the core, but is not required for the operation of a Vega node, and API clients are free to implement their own transaction signing.

A wallet takes the form of a file saved on the file system and is encrypted using the passphrase chosen by the user. A wallet is composed of a list of key pairs (Ed25519) used to sign transactions for the user of a wallet.

Generate configuration

The package provides a way to generate the configuration of the service before starting it, it can be used through the Vega command line like so:

vegawallet init

You can specify the -f flag to overwrite any existing configuration files (if found).

Run the service

Start the Vega wallet service with:

vegawallet service run

Create a wallet

Creating a wallet is done using a name and passphrase. If a wallet already exists, the action is aborted. New wallets are marshalled, encrypted (using the passphrase) and saved to a file on the file system. A session and accompanying JWT is created, and the JWT is returned to the user.

  • Request:

    {
      "wallet": "walletname",
      "passphrase": "supersecret"
    }
    
  • Command:

    curl -s -XPOST -d 'requestjson' http://127.0.0.1:1789/api/v1/wallets
    
  • Response:

    {
      "token": "verylongJWT"
    }
    

Logging in to a wallet

Logging in to a wallet is done using the wallet name and passphrase. The operation fails should the wallet not exist, or if the passphrase used is incorrect (i.e. the passphrase cannot be used to decrypt the wallet). On success, the wallet is loaded, a session is created and a JWT is returned to the user.

  • Request:

    {
      "wallet": "walletname",
      "passphrase": "supersecret"
    }
    
  • Command:

    curl -s -XPOST -d 'requestjson' http://127.0.0.1:1789/api/v1/auth/token
    
  • Response:

    {
      "token": "verylongJWT"
    }
    

Logging out from a wallet

Using the JWT returned when logging in, the session is recovered and removed from the service. The wallet can no longer be accessed using the token from this point on.

  • Request: n/a

  • Command:

    curl -s -XDELETE -H 'Authorization: Bearer verylongJWT' http://127.0.0.1:1789/api/v1/auth/token
    
  • Response:

    {
      "success": true
    }
    

List keys

Users can list all their public keys (with taint status, and metadata), if they provide the correct JWT. The service extracts the session from this token, and uses it to fetch the relevant wallet information to send back to the user.

  • Request: n/a

  • Command:

    curl -s -XGET -H "Authorization: Bearer verylongJWT" http://127.0.0.1:1789/api/v1/keys
    
  • Response:

    {
      "keys": [
        {
          "pub": "1122aabb...",
          "algo": "ed25519",
          "tainted": false,
          "meta": [
            {
              "key": "somekey",
              "value": "somevalue"
            }
          ]
        }
      ]
    }
    

Generate a new key pair

The user submits a valid JWT, and a passphrase. We recover the session of the user, and attempt to open the wallet using the passphrase. If the JWT is invalid, the session could not be recovered, or the wallet could not be opened, an error is returned. If all went well, a new key pair is generated, saved in the wallet, and the public key is returned.

  • Request:

    {
      "passphrase": "supersecret",
      "meta": [
        {
          "key": "somekey",
          "value": "somevalue"
        }
      ]
    }
    
  • Command:

    curl -s -XPOST -H 'Authorization: Bearer verylongJWT' -d 'requestjson' http://127.0.0.1:1789/api/v1/keys
    
  • Response:

    {
      "key": {
        "pub": "1122aabb...",
        "algo": "ed25519",
        "tainted": false,
        "meta": [
          {
            "key": "somekey",
            "value": "somevalue"
          }
        ]
      }
    }
    

Sign a transaction

Sign a transaction using the specified keypair.

  • Request:

    {
      "tx": "dGVzdGRhdGEK",
      "pubKey": "1122aabb...",
      "propagate": false
    }
    
  • Command:

    curl -s -XPOST -H "Authorization: Bearer verylongJWT" -d 'requestjson' http://127.0.0.1:1789/api/v1/messages
    
    
  • Response:

    {
      "signedTx": {
        "data": "dGVzdGRhdGEK",
        "sig": "...",
        "pubKey": "1122aabb..."
      }
    }
    
Propagate

As you can see the request payload has a field propagate (optional) if set to true, then the wallet service, if configured with a correct Vega node address will try to send the transaction on your behalf to the node after signing it successfully. The node address can be configured via the wallet service configuration file, by default it will point to a local instance of a Vega node.

Taint a key

  • Request:

    {
      "passphrase": "supersecret"
    }
    
  • Command:

    curl -s -XPUT -H "Authorization: Bearer verylongJWT" -d 'requestjson' http://127.0.0.1:1789/api/v1/keys/1122aabb/taint
    
    
  • Response:

    {
      "success": true
    }
    

Update key metadata

Overwrite all existing metadata with the new metadata.

  • Request:

    {
      "passphrase": "supersecret",
      "meta": [
        {
          "key": "newkey",
          "value": "newvalue"
        }
      ]
    }
    
  • Command:

    curl -s -XPUT -H "Authorization: Bearer verylongJWT" -d 'requestjson' http://127.0.0.1:1789/api/v1/keys/1122aabb/metadata
    
    
  • Response:

    {
      "success": true
    }
    

Issue a transaction

  • Request:

    {
      "pubKey": "8d06a20eb717938b746e0332686257ae39fa3d90847eb8ee0da3463732e968ba",
      "propagate": true,
      "orderCancellation": {
        "marketId": "YESYESYES"
      }
    }
    
  • Command:

    curl -s -XPOST -H "Authorization: Bearer verylongJWT" -d 'requestjson' http://127.0.0.1:1789/api/v1/command
    
  • Response:

    {
      "transaction": {
        "inputData": "dGVzdGRhdG9837420b4b3yb23ybc4o1ui23yEK",
        "signature": {
          "value": "7f6g9sf8f8s76dfa867fda",
          "algo": "vega/ed25519",
          "version": 1
        },
        "from": {
          "pubKey": "1122aabb..."
        },
        "version": 1
      }
    }
    

Documentation

Index

Constants

This section is empty.

Variables

View Source
var (
	ErrInvalidOrMissingToken  = newErrorResponse("invalid or missing token")
	ErrCouldNotReadRequest    = errors.New("could not read request")
	ErrCouldNotGetBlockHeight = errors.New("could not get last block height")
	ErrShouldBeBase64Encoded  = errors.New("should be base64 encoded")
)
View Source
var (
	ErrSessionNotFound = errors.New("session not found")
)

Functions

func ConfigExists

func ConfigExists(store Store) (bool, error)

func ExtractToken

ExtractToken this is public for testing purposes

func GenerateConfig

func GenerateConfig(store Store, overwrite bool) error

func NewAuth

func NewAuth(log *zap.Logger, cfgStore RSAStore, tokenExpiry time.Duration) (*auth, error)

Types

type Auth

type Auth interface {
	NewSession(name string) (string, error)
	VerifyToken(token string) (string, error)
	Revoke(token string) error
}

Auth ...

type Claims

type Claims struct {
	jwt.StandardClaims
	Session string
	Wallet  string
}

type Config

type Config struct {
	Level       encoding.LogLevel
	TokenExpiry encoding.Duration
	Port        int
	Host        string
	Nodes       NodesConfig
	Console     ConsoleConfig
}

func NewDefaultConfig

func NewDefaultConfig() Config

NewDefaultConfig creates an instance of the package specific configuration, given a pointer to a logger instance to be used for logging within the package.

type ConsoleConfig

type ConsoleConfig struct {
	URL       string
	LocalPort int
}

type CreateWalletRequest

type CreateWalletRequest struct {
	Wallet     string `json:"wallet"`
	Passphrase string `json:"passphrase"`
}

CreateWalletRequest describes the request for CreateWallet.

func ParseCreateWalletRequest

func ParseCreateWalletRequest(r *http.Request) (*CreateWalletRequest, commands.Errors)

type CreateWalletResponse

type CreateWalletResponse struct {
	Mnemonic string `json:"mnemonic"`
	Token    string `json:"token"`
}

CreateWalletResponse returns the authentication token and the auto-generated mnemonic of the created wallet.

type ErrorResponse

type ErrorResponse struct {
	ErrorStr string   `json:"error"`
	Details  []string `json:"details"`
}

func (ErrorResponse) Error

func (e ErrorResponse) Error() string

type ErrorsResponse

type ErrorsResponse struct {
	Errors commands.Errors `json:"errors"`
}

type GenKeyPairRequest

type GenKeyPairRequest struct {
	Passphrase string        `json:"passphrase"`
	Meta       []wallet.Meta `json:"meta"`
}

GenKeyPairRequest describes the request for GenerateKeyPair

func ParseGenKeyPairRequest

func ParseGenKeyPairRequest(r *http.Request) (*GenKeyPairRequest, commands.Errors)

type ImportWalletRequest

type ImportWalletRequest struct {
	Wallet     string `json:"wallet"`
	Passphrase string `json:"passphrase"`
	Mnemonic   string `json:"mnemonic"`
}

ImportWalletRequest describes the request for ImportWallet.

func ParseImportWalletRequest

func ParseImportWalletRequest(r *http.Request) (*ImportWalletRequest, commands.Errors)

type KeyResponse

type KeyResponse struct {
	Key wallet.PublicKey `json:"key"`
}

KeyResponse describes the response to a request that returns a single key.

type KeysResponse

type KeysResponse struct {
	Keys []wallet.PublicKey `json:"keys"`
}

KeysResponse describes the response to a request that returns a list of keys.

type LoginWalletRequest

type LoginWalletRequest struct {
	Wallet     string `json:"wallet"`
	Passphrase string `json:"passphrase"`
}

LoginWalletRequest describes the request for CreateWallet, LoginWallet.

func ParseLoginWalletRequest

func ParseLoginWalletRequest(r *http.Request) (*LoginWalletRequest, commands.Errors)

type NodeForward

type NodeForward interface {
	SendTxV2(context.Context, *commandspb.Transaction, api.SubmitTransactionV2Request_Type) error
	HealthCheck(context.Context) error
	LastBlockHeight(context.Context) (uint64, error)
}

NodeForward ...

type NodesConfig

type NodesConfig struct {
	Hosts   []string
	Retries uint64
}

type RSAKeys

type RSAKeys struct {
	Pub  []byte
	Priv []byte
}

func GenerateRSAKeys

func GenerateRSAKeys() (*RSAKeys, error)

type RSAStore

type RSAStore interface {
	GetRsaKeys() (*RSAKeys, error)
}

type Service

type Service struct {
	*httprouter.Router
	// contains filtered or unexported fields
}

func NewService

func NewService(log *zap.Logger, cfg *Config, rsaStore RSAStore, handler WalletHandler) (*Service, error)

func NewServiceWith

func NewServiceWith(log *zap.Logger, cfg *Config, h WalletHandler, a Auth, n NodeForward) (*Service, error)

func (*Service) CreateWallet

func (s *Service) CreateWallet(w http.ResponseWriter, r *http.Request, _ httprouter.Params)

func (*Service) DownloadWallet

func (s *Service) DownloadWallet(token string, w http.ResponseWriter, r *http.Request, _ httprouter.Params)

func (*Service) GenerateKeyPair

func (s *Service) GenerateKeyPair(t string, w http.ResponseWriter, r *http.Request, _ httprouter.Params)

func (*Service) GetPublicKey

func (s *Service) GetPublicKey(t string, w http.ResponseWriter, r *http.Request, ps httprouter.Params)

func (*Service) ImportWallet

func (s *Service) ImportWallet(w http.ResponseWriter, r *http.Request, _ httprouter.Params)

func (*Service) ListPublicKeys

func (s *Service) ListPublicKeys(t string, w http.ResponseWriter, r *http.Request, _ httprouter.Params)

func (*Service) Login

func (*Service) Revoke

func (s *Service) Revoke(t string, w http.ResponseWriter, _ *http.Request, _ httprouter.Params)

func (*Service) SignAny

func (s *Service) SignAny(t string, w http.ResponseWriter, r *http.Request, _ httprouter.Params)

func (*Service) SignTxCommitV2

func (s *Service) SignTxCommitV2(token string, w http.ResponseWriter, r *http.Request, p httprouter.Params)

func (*Service) SignTxSyncV2

func (s *Service) SignTxSyncV2(token string, w http.ResponseWriter, r *http.Request, p httprouter.Params)

func (*Service) SignTxV2

func (s *Service) SignTxV2(token string, w http.ResponseWriter, r *http.Request, p httprouter.Params)

func (*Service) Start

func (s *Service) Start() error

func (*Service) Stop

func (s *Service) Stop() error

func (*Service) TaintKey

func (s *Service) TaintKey(t string, w http.ResponseWriter, r *http.Request, ps httprouter.Params)

func (*Service) UpdateMeta

func (s *Service) UpdateMeta(t string, w http.ResponseWriter, r *http.Request, ps httprouter.Params)

func (*Service) VerifyAny

func (s *Service) VerifyAny(t string, w http.ResponseWriter, r *http.Request, _ httprouter.Params)

func (*Service) Version

func (s *Service) Version(w http.ResponseWriter, r *http.Request, _ httprouter.Params)

type SignAnyRequest

type SignAnyRequest struct {
	// InputData is the payload to generate a signature from. I should be
	// base 64 encoded.
	InputData string `json:"inputData"`
	// PubKey is used to retrieve the private key to sign the InputDate.
	PubKey string `json:"pubKey"`
	// contains filtered or unexported fields
}

SignAnyRequest describes the request for SignAny.

func ParseSignAnyRequest

func ParseSignAnyRequest(r *http.Request) (*SignAnyRequest, commands.Errors)

type SignAnyResponse

type SignAnyResponse struct {
	HexSignature    string `json:"hexSignature"`
	Base64Signature string `json:"base64Signature"`
}

SignAnyResponse describes the response for SignAny.

type Store

type Store interface {
	ConfigExists() (bool, error)
	RSAKeysExists() (bool, error)
	SaveConfig(*Config, bool) error
	SaveRSAKeys(*RSAKeys, bool) error
}

type SuccessResponse

type SuccessResponse struct {
	Success bool `json:"success"`
}

SuccessResponse describes the response to a request that returns a simple true/false answer.

type TaintKeyRequest

type TaintKeyRequest struct {
	Passphrase string `json:"passphrase"`
}

TaintKeyRequest describes the request for TaintKey.

func ParseTaintKeyRequest

func ParseTaintKeyRequest(r *http.Request, keyID string) (*TaintKeyRequest, commands.Errors)

type TokenResponse

type TokenResponse struct {
	Token string `json:"token"`
}

TokenResponse describes the response to a request that returns a token.

type UpdateMetaRequest

type UpdateMetaRequest struct {
	Passphrase string        `json:"passphrase"`
	Meta       []wallet.Meta `json:"meta"`
}

UpdateMetaRequest describes the request for UpdateMeta.

func ParseUpdateMetaRequest

func ParseUpdateMetaRequest(r *http.Request, keyID string) (*UpdateMetaRequest, commands.Errors)

type VerifyAnyRequest

type VerifyAnyRequest struct {
	// InputData is the payload to be verified. It should be base64 encoded.
	InputData string `json:"inputData"`
	// Signature is the signature to check against the InputData. It should be
	// base64 encoded.
	Signature string `json:"signature"`
	// PubKey is the public key used along the signature to check the InputData.
	PubKey string `json:"pubKey"`
	// contains filtered or unexported fields
}

VerifyAnyRequest describes the request for VerifyAny.

func ParseVerifyAnyRequest

func ParseVerifyAnyRequest(r *http.Request) (*VerifyAnyRequest, commands.Errors)

type VersionResponse

type VersionResponse struct {
	Version     string `json:"version"`
	VersionHash string `json:"versionHash"`
}

VersionResponse describes the response to a request that returns app version info.

type WalletHandler

type WalletHandler interface {
	CreateWallet(name, passphrase string) (string, error)
	ImportWallet(name, passphrase, mnemonic string) error
	LoginWallet(name, passphrase string) error
	LogoutWallet(name string)
	SecureGenerateKeyPair(name, passphrase string, meta []wallet.Meta) (string, error)
	GetPublicKey(name, pubKey string) (wallet.PublicKey, error)
	ListPublicKeys(name string) ([]wallet.PublicKey, error)
	SignTxV2(name string, req *walletpb.SubmitTransactionRequest, height uint64) (*commandspb.Transaction, error)
	SignAny(name string, inputData []byte, pubKey string) ([]byte, error)
	VerifyAny(inputData, sig []byte, pubKey string) (bool, error)
	TaintKey(name, pubKey, passphrase string) error
	UpdateMeta(name, pubKey, passphrase string, meta []wallet.Meta) error
	GetWalletPath(name string) (string, error)
}

WalletHandler ...

Directories

Path Synopsis
Package mocks is a generated GoMock package.
Package mocks is a generated GoMock package.
store
v1

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL