New address encoding (#356)

* [common] rework address encoding

* new address encoding

* replace offchain address by vtxo output key in DB

* merge migrations files into init one

* fix txbuilder fixtures

* fix transaction events
This commit is contained in:
Louis Singer
2024-10-18 16:50:07 +02:00
committed by GitHub
parent b1c9261f14
commit b536a9e652
58 changed files with 2243 additions and 1896 deletions

View File

@@ -3,63 +3,68 @@ package common
import (
"fmt"
"github.com/btcsuite/btcd/btcec/v2/schnorr"
"github.com/btcsuite/btcd/btcutil/bech32"
"github.com/decred/dcrd/dcrec/secp256k1/v4"
)
func EncodeAddress(
hrp string, userKey, aspKey *secp256k1.PublicKey,
) (addr string, err error) {
if userKey == nil {
err = fmt.Errorf("missing public key")
return
// Address represents an Ark address with HRP, ASP public key, and VTXO Taproot public key
type Address struct {
HRP string
Asp *secp256k1.PublicKey
VtxoTapKey *secp256k1.PublicKey
}
// Encode converts the address to its bech32m string representation
func (a *Address) Encode() (string, error) {
if a.Asp == nil {
return "", fmt.Errorf("missing asp public key")
}
if aspKey == nil {
err = fmt.Errorf("missing asp public key")
return
}
if hrp != Liquid.Addr && hrp != LiquidTestNet.Addr {
err = fmt.Errorf("invalid prefix")
return
if a.VtxoTapKey == nil {
return "", fmt.Errorf("missing vtxo tap public key")
}
combinedKey := append(
aspKey.SerializeCompressed(), userKey.SerializeCompressed()...,
schnorr.SerializePubKey(a.Asp), schnorr.SerializePubKey(a.VtxoTapKey)...,
)
grp, err := bech32.ConvertBits(combinedKey, 8, 5, true)
if err != nil {
return
return "", err
}
addr, err = bech32.EncodeM(hrp, grp)
return
return bech32.EncodeM(a.HRP, grp)
}
func DecodeAddress(
addr string,
) (hrp string, userKey, aspKey *secp256k1.PublicKey, err error) {
// DecodeAddress parses a bech32m encoded address string and returns an Address object
func DecodeAddress(addr string) (*Address, error) {
if len(addr) == 0 {
return nil, fmt.Errorf("address is empty")
}
prefix, buf, err := bech32.DecodeNoLimit(addr)
if err != nil {
return
return nil, err
}
if prefix != Liquid.Addr && prefix != LiquidTestNet.Addr && prefix != LiquidRegTest.Addr {
err = fmt.Errorf("invalid prefix")
return
return nil, fmt.Errorf("invalid prefix")
}
grp, err := bech32.ConvertBits(buf, 5, 8, false)
if err != nil {
return
return nil, err
}
aKey, err := secp256k1.ParsePubKey(grp[:33])
aKey, err := schnorr.ParsePubKey(grp[:32])
if err != nil {
err = fmt.Errorf("failed to parse public key: %s", err)
return
return nil, fmt.Errorf("failed to parse public key: %s", err)
}
uKey, err := secp256k1.ParsePubKey(grp[33:])
vtxoKey, err := schnorr.ParsePubKey(grp[32:])
if err != nil {
err = fmt.Errorf("failed to parse asp public key: %s", err)
return
return nil, fmt.Errorf("failed to parse asp public key: %s", err)
}
hrp = prefix
userKey = uKey
aspKey = aKey
return
return &Address{
HRP: prefix,
Asp: aKey,
VtxoTapKey: vtxoKey,
}, nil
}