zanolib

package module
v0.0.2 Latest Latest
Warning

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

Go to latest
Published: Mar 10, 2025 License: MIT Imports: 13 Imported by: 0

README

GoDoc

zanolib

Zano interactions library, including address manipulation.

The goal is to allow full control over signatures performed when using Zano's simplewallet in view-only mode on edge nodes. The view-only wallet can have a RPC enabled that allows monitoring balance, new transactions, and generate unsigned transactions. An unsigned transaction generated by simplewallet can be then passed to this library for signature.

The goal is to implement more secure processes to store the secret, if possible.

Offline signatures

Compatible Zano version: 2.1.0.382

This library is able to load unsigned transactions. There are however a few caveats there:

  • Because the unsigned transaction is a binary format NOT meant to be portable, it only work between specific versions of Zano. This library is tested against a specific version of Zano and may not work with newer versions. Blob files aren't versioned so it would be difficult to detect structure automatically as is.
  • For now this library only supports simple ZC→ZC transactions.

Usage

// first, initialize a wallet based on a securely stored secret
// note: set flag to 1 if this is an auditable wallet
wallet, err := zanolib.LoadSpendSecret(secret, 0)
if err != nil {
    // ...
}
// read the finalize tx params structure
ftp, err := wallet.ParseFTP(must(os.ReadFile("zano_tx_unsigned")))
if err != nil {
    // ...
}
// inspect ftp to make sure this is the transaction you want to sign
// generate finalized transaction
finalized, err := wallet.Sign(rand.Reader, ftp, nil)
if err != nil {
    // ...
}
// write to disk
os.WriteFile("zano_tx_signed", must(wallet.Encrypt(finalized)), 0600)
// now you can pass zano_tx_signed to your view only wallet for broadcast

Documentation

Index

Constants

This section is empty.

Variables

View Source
var (
	CRYPTO_HDS_OUT_AMOUNT_BLINDING_MASK = []byte("ZANO_HDS_OUT_AMOUNT_BLIND_MASK_\x00")
)

Functions

This section is empty.

Types

type Address

type Address struct {
	Type      AddressType
	Flags     uint8
	SpendKey  []byte
	ViewKey   []byte
	PaymentId []byte
}

func ParseAddress

func ParseAddress(addr string) (*Address, error)

ParseAddress will parse a zano address and return and Address object containing the address

func (*Address) Debug

func (addr *Address) Debug() string

func (*Address) SetPaymentId

func (addr *Address) SetPaymentId(paymentId []byte) error

SetPaymentId sets the payment ID for the given address, and updates the address type accordingly.

func (*Address) String

func (addr *Address) String() string

String returns the address encoded as a standard Zano address

type AddressType

type AddressType uint64
const (
	PublicAddress           AddressType = 0xc5   // Zx
	PublicIntegAddress      AddressType = 0x3678 // iZ
	PublicIntegAddressV2    AddressType = 0x36f8 // iZ (new format)
	PublicAuditAddress      AddressType = 0x98c8 // aZx
	PublicAuditIntegAddress AddressType = 0x8a49 // aiZX
)

func (AddressType) Auditable

func (a AddressType) Auditable() bool

func (AddressType) HasFlags

func (a AddressType) HasFlags() bool

func (AddressType) String

func (a AddressType) String() string

type FinalizeTxParam

type FinalizeTxParam struct {
	UnlockTime           uint64
	Extra                []*zanobase.Variant         // currency::extra_v
	Attachments          []*zanobase.Variant         // currency::attachment_v
	CryptAddress         *zanobase.AccountPublicAddr // currency::account_public_address
	TxOutsAttr           uint8
	Shuffle              bool
	Flags                uint8
	MultisigId           zanobase.Value256 // crypto::hash
	Sources              []*TxSource       // currency::tx_source_entry
	SelectedTransfers    []zanobase.Varint // not sure why, but this is encoded as "01 00" in the bytestream
	PreparedDestinations []*TxDest         // currency::tx_destination_entry
	ExpirationTime       uint64
	SpendPubKey          *zanobase.Point // only for validations
	TxVersion            uint64
	TxHardforkId         uint64
	ModeSeparateFee      uint64
}

func ParseFTP

func ParseFTP(buf, viewSecretKey []byte) (*FinalizeTxParam, error)

type FinalizedTx

type FinalizedTx struct {
	Tx             *zanobase.Transaction     `json:"tx"`
	TxId           zanobase.Value256         `json:"txid"`         // might be zeroes?
	OneTimeKey     *zanobase.Scalar          `json:"one_time_key"` // crypto::secret_key
	FTP            *FinalizeTxParam          `json:"ftp"`
	HtlcOrigin     string                    `json:"htlc_origin"`
	OutsKeyImages  []*zanobase.KeyImageIndex `json:"outs_key_images,omitempty"` // pairs (out_index, key_image) for each change output
	Derivation     zanobase.Value256         `json:"derivation"`                // crypto::key_derivation, a ec_point
	WasNotPrepared bool                      `json:"was_not_prepared"`          // true if tx was not prepared/created for some good reason (e.g. not enough outs for UTXO defragmentation tx). Because we decided not to throw exceptions for non-error cases. -- sowle
}

func ParseFinalized

func ParseFinalized(buf, viewSecretKey []byte) (*FinalizedTx, error)

type GenContext

type GenContext struct {
}

type TxDest

type TxDest struct {
	Amount          uint64
	Addr            []*zanobase.AccountPublicAddr // account_public_address; destination address, in case of 1 address - txout_to_key, in case of more - txout_multisig
	MinimumSigs     uint64                        // if txout_multisig: minimum signatures that are required to spend this output (minimum_sigs <= addr.size())  IF txout_to_key - not used
	AmountToProvide uint64                        // amount money that provided by initial creator of tx, used with partially created transactions
	UnlockTime      uint64                        //
	HtlcOptions     *TxDestHtlcOut                // destination_option_htlc_out
	AssetId         *zanobase.Point               // not blinded, not premultiplied
	Flags           uint64                        // set of flags (see tx_destination_entry_flags)
}

func (*TxDest) AmountCommitment

func (dst *TxDest) AmountCommitment(scalar *edwards25519.Scalar, ogc *zanobase.GenContext, i int) *edwards25519.Point

func (*TxDest) BlindedAssetId

func (dst *TxDest) BlindedAssetId(scalar *edwards25519.Scalar, ogc *zanobase.GenContext, i int) *edwards25519.Point

func (*TxDest) ConcealingPoint

func (dst *TxDest) ConcealingPoint(scalar *edwards25519.Scalar, ogc *zanobase.GenContext, i int) *edwards25519.Point

func (*TxDest) StealthAddress

func (dst *TxDest) StealthAddress(scalar *edwards25519.Scalar, ogc *zanobase.GenContext, i int) *edwards25519.Point

type TxDestHtlcOut

type TxDestHtlcOut struct {
	Expiration uint64
	HtlcHash   zanobase.Value256 // crypto::hash
}

type TxSource

type TxSource struct {
	Outputs                    []*TxSourceOutputEntry
	RealOutput                 uint64
	RealOutTxKey               *zanobase.Point  // crypto::public_key
	RealOutAmountBlindingMask  *zanobase.Scalar // crypto::scalar_t
	RealOutAssetIdBlindingMask *zanobase.Scalar // crypto::scalar_t
	RealOutInTxIndex           uint64           // size_t, index in transaction outputs vector
	Amount                     uint64
	TransferIndex              uint64
	MultisigId                 zanobase.Value256 // crypto::hash if txin_multisig: multisig output id
	MsSigsCount                uint64            // size_t
	MsKeysCount                uint64            // size_t
	SeparatelySignedTxComplete bool
	HtlcOrigin                 string // for htlc, specify origin. len = 1, content = "\x00" ?
	// contains filtered or unexported fields
}

func (*TxSource) IsZC

func (src *TxSource) IsZC() bool

type TxSourceOutputEntry

type TxSourceOutputEntry struct {
	OutReference     *zanobase.Variant // TxOutRef // either global output index or ref_by_id
	StealthAddress   *zanobase.Point   // crypto::public_key, a.k.a output's one-time public key
	ConcealingPoint  *zanobase.Point   // only for ZC outputs
	AmountCommitment *zanobase.Point   // only for ZC outputs
	BlindedAssetID   *zanobase.Point   // only for ZC outputs
}

type Wallet

type Wallet struct {
	SpendPrivKey *edwards25519.Scalar
	SpendPubKey  *edwards25519.Point
	ViewPrivKey  *edwards25519.Scalar
	ViewPubKey   *edwards25519.Point
	Flags        uint8 // flag 1 = auditable
}

func LoadSpendSecret

func LoadSpendSecret(pk []byte, flags uint8) (*Wallet, error)

LoadSpendSecret initializesd a Wallet based on a spend secret as found in zano if you run spendkey. It will automatically derive the view key using the appropriate method for Zano.

Set flags to zero for normal keys, or 1 for auditable keys.

func (*Wallet) Address

func (w *Wallet) Address() *Address

Address returns this wallet's address.

func (*Wallet) Encrypt

func (w *Wallet) Encrypt(data any) ([]byte, error)

Encrypt will serialize and encrypt whatever data is passed (can be a FTP or a finalized transaction) so it can be read again.

func (*Wallet) ParseFTP

func (w *Wallet) ParseFTP(buf []byte) (*FinalizeTxParam, error)

func (*Wallet) ParseFinalized

func (w *Wallet) ParseFinalized(buf []byte) (*FinalizedTx, error)

func (*Wallet) Sign

func (w *Wallet) Sign(rnd io.Reader, ftp *FinalizeTxParam, oneTimeKey *edwards25519.Scalar) (*FinalizedTx, error)

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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