gobip352

package module
v0.1.4 Latest Latest
Warning

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

Go to latest
Published: Apr 23, 2024 License: MIT Imports: 14 Imported by: 4

README

GOBip352

This library provides the basic functions for working with BIP352. It takes care of the elliptic curve computations and some periphery around creating outputs and scanning. This library is not a full wallet. For example the current scope does not include checking whether inputs are eligible as Inputs For Shared Secret Derivation.

Todo

  • Consider using fixed length byte arrays instead of slice, will help with "type-safety" of keys, hashes, compressed, x-only, scalars
  • Sending vectors passing
  • Receiving vectors passing
  • Include vin checking module (include functionality that allows for checking whether inputs are eligible according to the BIP)
  • Standardize errors as types
  • Benchmark a map of labels against looping over the slice of labels in matching

Documentation

Index

Constants

This section is empty.

Variables

View Source
var NumsH = []byte{80, 146, 155, 116, 193, 160, 73, 84, 183, 139, 75, 96, 53, 233, 122, 94, 7, 138, 90, 15, 40, 236, 150, 213, 71, 191, 238, 154, 206, 128, 58, 192}

NumsH = 0x50929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0

Functions

func AddPrivateKeys

func AddPrivateKeys(secKey1, secKey2 [32]byte) [32]byte

func AddPublicKeys

func AddPublicKeys(publicKeyBytes1, publicKeyBytes2 [33]byte) ([33]byte, error)

func ComputeInputHash

func ComputeInputHash(vins []*Vin, publicKeySum [33]byte) ([32]byte, error)

ComputeInputHash computes the input_hash for a transaction as per the specification. vins: does not need to contain public key or secret key, only needs the txid and vout; txid has to be in the normal human-readable format sumPublicKeys: 33 byte compressed public key sum of the inputs for shared derivation https://github.com/josibake/bips/blob/silent-payments-bip/bip-0352.mediawiki#inputs-for-shared-secret-derivation

func ComputeTK

func ComputeTK(sharedSecret [33]byte, k uint32) ([32]byte, error)

func ConvertPointsToPublicKey

func ConvertPointsToPublicKey(x, y *big.Int) (*btcec.PublicKey, error)

func ConvertToFixedLength32

func ConvertToFixedLength32(input []byte) [32]byte

func ConvertToFixedLength33

func ConvertToFixedLength33(input []byte) [33]byte

func CreateAddress

func CreateAddress(scanPubKeyBytes, bMKeyBytes [33]byte, mainnet bool, version uint8) (string, error)

func CreateLabelPublicKey

func CreateLabelPublicKey(labelTweak [32]byte) [33]byte

func CreateLabelTweak

func CreateLabelTweak(scanSecKey [32]byte, m uint32) ([32]byte, error)

func CreateLabeledAddress

func CreateLabeledAddress(scanPubKeyBytes, spendPubKeyBytes [33]byte, mainnet bool, version uint8, scanSecKey [32]byte, m uint32) (string, error)

func CreateLabelledSpendPubKey added in v0.1.3

func CreateLabelledSpendPubKey(spendPubKey, labelPubKey [33]byte) ([33]byte, error)

CreateLabelledSpendPubKey Returns the labeled spend pub key

B_m = B_spend + label

todo should this be included?

func CreateOutput added in v0.1.2

func CreateOutput() ([32]byte, error)

CreateOutput todo a function that creates an output from a recipient with the necessary data

func CreateOutputPubKey

func CreateOutputPubKey(sharedSecret [33]byte, receiverSpendPubKey [33]byte, k uint32) ([32]byte, error)

CreateOutputPubKey returns 32 byte x-only pubKey

func CreateOutputPubKeyTweak

func CreateOutputPubKeyTweak(sharedSecret [33]byte, receiverSpendPubKey [33]byte, k uint32) ([32]byte, [32]byte, error)

CreateOutputPubKeyTweak same as CreateOutputPubKey but this also returns the tweak of the output and the 33 byte compressed output

func CreatePublicTweakData

func CreatePublicTweakData(publicKeys []*btcec.PublicKey, smallestOutpoint []byte) ([]byte, error)

func CreateSharedSecret

func CreateSharedSecret(publicComponent [33]byte, secretComponent [32]byte, inputHash *[32]byte) ([33]byte, error)

CreateSharedSecret The public component is dependent on whether this function is called from the sender or receiver side. The input_hash is the same for both sides. The input_hash can be nil if the publicComponent already incorporates the inputHash in case of a tweak as it would be for light clients

For the sender publicComponent is B_scan and secretComponent is a_sum

shared_secret = (a_sum * input_hash) * B_scan [Sender]

For the receiver publicComponent is A_sum and the secretComponent is b_scan

shared_secret = (b_scan * input_hash) * A_sum [Receiver, Full node scenario]

shared_secret = b_scan * A_tweaked [Receiver, Light client scenario]

func DecodeSilentPaymentAddress

func DecodeSilentPaymentAddress(address string, mainnet bool) (string, []byte, uint8, error)

DecodeSilentPaymentAddress Returns: 1. hrp 2. the raw byte data that was encoded 3. the version 4. the error, if one occurs

func DecodeSilentPaymentAddressToKeys

func DecodeSilentPaymentAddressToKeys(address string, mainnet bool) (scanPubKeyBytes, spendPubKeyBytes [33]byte, err error)

func FindSmallestOutpoint

func FindSmallestOutpoint(vins []*Vin) ([]byte, error)

FindSmallestOutpoint txid has to be in the normal human-readable format

func Hash160

func Hash160(data []byte) []byte

Hash160 performs a RIPEMD160(SHA256(data)) hash on the given data

func MultPrivateKeys

func MultPrivateKeys(secKey1, secKey2 [32]byte) [32]byte

func NegatePublicKey

func NegatePublicKey(pk [33]byte) ([33]byte, error)

func ParseWitnessScript

func ParseWitnessScript(data []byte) ([][]byte, error)

ParseWitnessScript parses a hex-encoded witness script and returns the actual witness data as a list

func RecursiveAddPrivateKeys

func RecursiveAddPrivateKeys(secretKeys [][32]byte) [32]byte

RecursiveAddPrivateKeys this is a simple addition of given privateKeys Keep in mind that this function does not negate privateKeys this has to be done before calling this function

func ReverseBytes

func ReverseBytes(bytes []byte) []byte

func SenderCreateOutputs

func SenderCreateOutputs(recipients []*Recipient, vins []*Vin, mainnet bool) error

SenderCreateOutputs recipients: must include result will be stored in the recipients. vins: has to include the txids and vouts

func SerU32

func SerU32(num uint32) ([]byte, error)

func SumPublicKeys

func SumPublicKeys(pubKeys [][33]byte) ([33]byte, error)

func TaggedHash

func TaggedHash(tag string, msg []byte) [32]byte

Types

type AddressHRPError

type AddressHRPError struct{}

func (AddressHRPError) Error

func (e AddressHRPError) Error() string

type DecodingLimitExceeded

type DecodingLimitExceeded struct{}

func (DecodingLimitExceeded) Error

func (e DecodingLimitExceeded) Error() string

type FoundOutput added in v0.1.1

type FoundOutput struct {
	Output      [32]byte  // x-only pubKey
	SecKeyTweak [32]byte  // tweak for the output
	Label       *[33]byte // public key of the label is a label was matched todo should this include the entire label?
}

func ReceiverScanTransaction

func ReceiverScanTransaction(scanKey [32]byte, receiverSpendPubKey [33]byte, labels []Label, txOutputs [][32]byte, publicComponent [33]byte, inputHash *[32]byte) ([]*FoundOutput, error)

ReceiverScanTransaction scanKey: scanning secretKey of the receiver receiverSpendPubKey: spend pubKey of the receiver txOutputs: x-only outputs of the specific transaction labels: existing label public keys as bytes [wallets should always check for the change label] publicComponent: either A_sum or tweaked (A_sum * input_hash) if tweaked inputHash should be nil or the computation will be flawed inputHash: 32 byte can be nil if publicComponent is a tweak and already includes the input_hash

type FullTestCase

type FullTestCase struct {
	Comment string `json:"comment"`
	Sending []struct {
		Given struct {
			Vin []struct {
				Txid        string `json:"txid"`
				Vout        uint32 `json:"vout"`
				ScriptSig   string `json:"scriptSig"`
				Txinwitness string `json:"txinwitness"`
				Prevout     struct {
					ScriptPubKey struct {
						Hex  string `json:"hex"`
						Type string `json:"type"`
					} `json:"scriptPubKey"`
				} `json:"prevout"`
				PrivateKey string `json:"private_key"`
			} `json:"vin"`
			Recipients []string `json:"recipients"`
		} `json:"given"`
		Expected struct {
			Outputs []string `json:"outputs"`
		} `json:"expected"`
	} `json:"sending"`
	Receiving []struct {
		Given struct {
			Vin         []VinReceiveTestCase `json:"vin"`
			Outputs     []string             `json:"outputs"`
			KeyMaterial struct {
				SpendPrivKey string `json:"spend_priv_key"`
				ScanPrivKey  string `json:"scan_priv_key"`
			} `json:"key_material"`
			Labels []uint32 `json:"labels"`
		} `json:"given"`
		Expected struct {
			Addresses []string `json:"addresses"`
			Outputs   []struct {
				PubKey       string `json:"pub_key"`
				PrivKeyTweak string `json:"priv_key_tweak"`
				Signature    string `json:"signature"`
			} `json:"outputs"`
			Tweak string `json:"tweak"`
		} `json:"expected"`
	} `json:"receiving"`
}

func LoadFullCaseData

func LoadFullCaseData(t *testing.T) ([]FullTestCase, error)

type Label

type Label struct {
	PubKey  [33]byte // compressed pubKey of the label
	Tweak   [32]byte // tweak/secKey to produce the labels pubKey
	Address string   // todo the corresponding address for the label, still needs a good API for instantiating with this data
	M       uint32
}

func CreateLabel

func CreateLabel(scanSecKey [32]byte, m uint32) (Label, error)

func MatchLabels

func MatchLabels(txOutput, pk [33]byte, labels []Label) (*Label, error)

type Recipient

type Recipient struct {
	SilentPaymentAddress string
	ScanPubKey           *btcec.PublicKey
	SpendPubKey          *btcec.PublicKey
	Output               [32]byte // the resulting taproot x-only output
	Amount               uint64
	Data                 map[string]any // in order to allocate data to a recipient that needs to be known after handling
}

type TypeUTXO

type TypeUTXO uint8
const (
	P2TR TypeUTXO = iota
	P2WPKH
	P2PKH
	P2SH

	NoType
)

type Vin

type Vin struct {
	Txid         [32]byte  // txid has to be in the normal human-readable format
	Vout         uint32    // output index of the input
	Amount       uint64    // value of the utxo in satoshi (100_000_000 sat = 1 Bitcoin)
	PublicKey    *[33]byte // 33 byte compressed public key or 32 byte taproot x-only key
	SecretKey    *[32]byte // 32 byte secret key
	Taproot      bool      // indicates whether input is taproot or not. taproot outputs have to be even hence the flag has to be set, so we can check for negation
	Witness      [][]byte  // witness data for the input
	ScriptPubKey []byte    // the scriptPubKey of the input
	ScriptSig    []byte    // used for p2pkh
}

type VinReceiveTestCase

type VinReceiveTestCase struct {
	Txid        string `json:"txid"`
	Vout        uint32 `json:"vout"`
	ScriptSig   string `json:"scriptSig"`
	Txinwitness string `json:"txinwitness"`
	Prevout     struct {
		ScriptPubKey struct {
			Hex  string `json:"hex"`
			Type string `json:"type"`
		} `json:"scriptPubKey"`
	} `json:"prevout"`
}

Jump to

Keyboard shortcuts

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