Skip to content

Commit

Permalink
multi: add address version to database
Browse files Browse the repository at this point in the history
This commit adds the recently added address version to the database as
well.
  • Loading branch information
guggero committed Sep 19, 2023
1 parent 0c6cf23 commit 33f722e
Show file tree
Hide file tree
Showing 13 changed files with 155 additions and 113 deletions.
62 changes: 33 additions & 29 deletions address/address.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,23 +23,17 @@ var (
// ErrUnsupportedHRP is an error returned when we attempt to encode a
// Taproot Asset address with an HRP for a network without Taproot Asset
// support.
ErrUnsupportedHRP = errors.New(
"address: unsupported HRP value",
)
ErrUnsupportedHRP = errors.New("address: unsupported HRP value")

// ErrMismatchedHRP is an error returned when we attempt to decode a
// Taproot Asset address with an HRP that does not match the expected
// network.
ErrMismatchedHRP = errors.New(
"address: network mismatch",
)
ErrMismatchedHRP = errors.New("address: network mismatch")

// ErrInvalidBech32m is an error returned when we attempt to decode a
// Taproot Asset address from a string that is not a valid bech32m
// string.
ErrInvalidBech32m = errors.New(
"address: invalid bech32m string",
)
ErrInvalidBech32m = errors.New("address: invalid bech32m string")

// ErrInvalidAmountCollectible is an error returned when we attempt to
// create a Taproot Asset address for a Collectible asset with an amount
Expand All @@ -57,34 +51,28 @@ var (

// ErrUnsupportedAssetType is an error returned when we attempt to
// create a Taproot Asset address for a non-standard asset type.
ErrUnsupportedAssetType = errors.New(
"address: unsupported asset type",
)
ErrUnsupportedAssetType = errors.New("address: unsupported asset type")

// ErrNoAddr is returned if no address is found in the address store.
ErrNoAddr = errors.New(
"address: no address found",
)
ErrNoAddr = errors.New("address: no address found")

// ErrScriptKeyNotFound is returned when a script key is not found in
// the local database.
ErrScriptKeyNotFound = errors.New(
"script key not found",
)
ErrScriptKeyNotFound = errors.New("script key not found")

// ErrUnknownVersion is returned when encountering an address with an
// unrecognised version number.
ErrUnknownVersion = errors.New("unknown address version number")
ErrUnknownVersion = errors.New("address: unknown version number")
)

// Version denotes the version of the Tap address.
// Version denotes the version of a Taproot Asset address format.
type Version uint8

const (
// V0 is the initial Tap address version.
// V0 is the initial Taproot Asset address format version.
V0 Version = 0

// LatestVersion is the latest supported Tap address version.
// LatestVersion is the latest supported Taproot Asset address version.
latestVersion = V0
)

Expand Down Expand Up @@ -141,7 +129,7 @@ type Tap struct {
//
// TODO(ffranr): This function takes many arguments. Add a struct to better
// organise its arguments.
func New(genesis asset.Genesis, groupKey *btcec.PublicKey,
func New(version Version, genesis asset.Genesis, groupKey *btcec.PublicKey,
groupSig *schnorr.Signature, scriptKey btcec.PublicKey,
internalKey btcec.PublicKey, amt uint64,
tapscriptSibling *commitment.TapscriptPreimage,
Expand Down Expand Up @@ -169,6 +157,11 @@ func New(genesis asset.Genesis, groupKey *btcec.PublicKey,
return nil, ErrUnsupportedHRP
}

// Check the version of the address format.
if IsUnknownVersion(version) {
return nil, ErrUnknownVersion
}

// We can only use a tapscript sibling that is not a Taproot Asset
// commitment.
if tapscriptSibling != nil {
Expand All @@ -183,7 +176,7 @@ func New(genesis asset.Genesis, groupKey *btcec.PublicKey,
}

payload := Tap{
Version: V0,
Version: version,
ChainParams: net,
AssetVersion: asset.V0,
AssetID: genesis.ID(),
Expand Down Expand Up @@ -317,8 +310,9 @@ func (a *Tap) TaprootOutputKey() (*btcec.PublicKey, error) {
// EncodeRecords determines the non-nil records to include when encoding an
// address at runtime.
func (a *Tap) EncodeRecords() []tlv.Record {
records := make([]tlv.Record, 0, 6)
records = append(records, newAddressVersionRecord(&a.AssetVersion))
records := make([]tlv.Record, 0, 9)
records = append(records, newAddressVersionRecord(&a.Version))
records = append(records, newAddressAssetVersionRecord(&a.AssetVersion))
records = append(records, newAddressAssetID(&a.AssetID))

if a.GroupKey != nil {
Expand All @@ -337,7 +331,6 @@ func (a *Tap) EncodeRecords() []tlv.Record {
records = append(
records, newProofCourierAddrRecord(&a.ProofCourierAddr),
)
records = append(records, newVersionRecord(&a.Version))

return records
}
Expand All @@ -346,15 +339,15 @@ func (a *Tap) EncodeRecords() []tlv.Record {
// decoding.
func (a *Tap) DecodeRecords() []tlv.Record {
return []tlv.Record{
newAddressVersionRecord(&a.AssetVersion),
newAddressVersionRecord(&a.Version),
newAddressAssetVersionRecord(&a.AssetVersion),
newAddressAssetID(&a.AssetID),
newAddressGroupKeyRecord(&a.GroupKey),
newAddressScriptKeyRecord(&a.ScriptKey),
newAddressInternalKeyRecord(&a.InternalKey),
newAddressTapscriptSiblingRecord(&a.TapscriptSibling),
newAddressAmountRecord(&a.Amount),
newProofCourierAddrRecord(&a.ProofCourierAddr),
newVersionRecord(&a.Version),
}
}

Expand Down Expand Up @@ -408,6 +401,17 @@ func (a *Tap) String() string {
a.AssetID, a.Amount, a.ScriptKey.SerializeCompressed())
}

// IsUnknownVersion returns true if the address version is not recognized by
// this implementation of tap.
func IsUnknownVersion(v Version) bool {
switch v {
case V0:
return false
default:
return true
}
}

// DecodeAddress parses a bech32m encoded Taproot Asset address string and
// returns the HRP and address TLV.
func DecodeAddress(addr string, net *ChainParams) (*Tap, error) {
Expand Down
47 changes: 34 additions & 13 deletions address/address_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,8 @@ var (
}
)

func randAddress(t *testing.T, net *ChainParams, groupPubKey, sibling bool,
amt *uint64, assetType asset.Type) (*Tap, error) {
func randAddress(t *testing.T, net *ChainParams, v Version, groupPubKey,
sibling bool, amt *uint64, assetType asset.Type) (*Tap, error) {

t.Helper()

Expand Down Expand Up @@ -71,8 +71,8 @@ func randAddress(t *testing.T, net *ChainParams, groupPubKey, sibling bool,
proofCourierAddr := RandProofCourierAddr(t)

return New(
genesis, groupKey, groupSig, pubKeyCopy1, pubKeyCopy2, amount,
tapscriptSibling, net, proofCourierAddr,
v, genesis, groupKey, groupSig, pubKeyCopy1, pubKeyCopy2,
amount, tapscriptSibling, net, proofCourierAddr,
)
}

Expand All @@ -82,7 +82,7 @@ func randEncodedAddress(t *testing.T, net *ChainParams, groupPubKey,
t.Helper()

newAddr, err := randAddress(
t, net, groupPubKey, sibling, nil, assetType,
t, net, V0, groupPubKey, sibling, nil, assetType,
)
if err != nil {
return nil, "", err
Expand Down Expand Up @@ -115,7 +115,7 @@ func TestNewAddress(t *testing.T) {
name: "normal address",
f: func() (*Tap, error) {
return randAddress(
t, &TestNet3Tap, false, false, nil,
t, &TestNet3Tap, V0, false, false, nil,
asset.Normal,
)
},
Expand All @@ -125,7 +125,7 @@ func TestNewAddress(t *testing.T) {
name: "collectible address with group key",
f: func() (*Tap, error) {
return randAddress(
t, &MainNetTap, true, false, nil,
t, &MainNetTap, V0, true, false, nil,
asset.Collectible,
)
},
Expand All @@ -135,7 +135,7 @@ func TestNewAddress(t *testing.T) {
name: "collectible address with group key and sibling",
f: func() (*Tap, error) {
return randAddress(
t, &MainNetTap, true, true, nil,
t, &MainNetTap, V0, true, true, nil,
asset.Collectible,
)
},
Expand All @@ -146,7 +146,7 @@ func TestNewAddress(t *testing.T) {
f: func() (*Tap, error) {
zeroAmt := uint64(0)
return randAddress(
t, &TestNet3Tap, false, false,
t, &TestNet3Tap, V0, false, false,
&zeroAmt, asset.Normal,
)
},
Expand All @@ -157,8 +157,8 @@ func TestNewAddress(t *testing.T) {
f: func() (*Tap, error) {
badAmt := uint64(2)
return randAddress(
t, &TestNet3Tap, false, false, &badAmt,
asset.Collectible,
t, &TestNet3Tap, V0, false, false,
&badAmt, asset.Collectible,
)
},
err: ErrInvalidAmountCollectible,
Expand All @@ -167,12 +167,22 @@ func TestNewAddress(t *testing.T) {
name: "invalid hrp",
f: func() (*Tap, error) {
return randAddress(
t, &invalidNet, false, false, nil,
t, &invalidNet, V0, false, false, nil,
asset.Normal,
)
},
err: ErrUnsupportedHRP,
},
{
name: "invalid version",
f: func() (*Tap, error) {
return randAddress(
t, &TestNet3Tap, Version(123), false,
false, nil, asset.Normal,
)
},
err: ErrUnknownVersion,
},
}

for _, testCase := range testCases {
Expand Down Expand Up @@ -333,11 +343,22 @@ func TestAddressEncoding(t *testing.T) {
},
err: ErrInvalidBech32m,
},
{
name: "unknown version number in constructor",
f: func() (*Tap, string, error) {
_, err := randAddress(
t, &TestNet3Tap, Version(255), false,
true, nil, asset.Collectible,
)
return nil, "", err
},
err: ErrUnknownVersion,
},
{
name: "unknown version number",
f: func() (*Tap, string, error) {
newAddr, err := randAddress(
t, &TestNet3Tap, false, true, nil,
t, &TestNet3Tap, V0, false, true, nil,
asset.Collectible,
)
require.NoError(t, err)
Expand Down
6 changes: 3 additions & 3 deletions address/book.go
Original file line number Diff line number Diff line change
Expand Up @@ -232,9 +232,9 @@ func (b *Book) NewAddressWithKeys(ctx context.Context, assetID asset.ID,
}

baseAddr, err := New(
*assetGroup.Genesis, groupKey, groupSig, *scriptKey.PubKey,
*internalKeyDesc.PubKey, amount, tapscriptSibling, &b.cfg.Chain,
proofCourierAddr,
V0, *assetGroup.Genesis, groupKey, groupSig,
*scriptKey.PubKey, *internalKeyDesc.PubKey, amount,
tapscriptSibling, &b.cfg.Chain, proofCourierAddr,
)
if err != nil {
return nil, fmt.Errorf("unable to make new addr: %w", err)
Expand Down
2 changes: 1 addition & 1 deletion address/mock.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ func RandAddr(t testing.TB, params *ChainParams,
})

tapAddr, err := New(
genesis, groupPubKey, groupSig, *scriptKey.PubKey,
V0, genesis, groupPubKey, groupSig, *scriptKey.PubKey,
*internalKey.PubKey(), amount, tapscriptSibling, params,
proofCourierAddr,
)
Expand Down
38 changes: 19 additions & 19 deletions address/records.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,36 +13,42 @@ import (
type addressTLVType = tlv.Type

const (
// addrAssetVersionType is the TLV type of the address's asset version.
addrAssetVersionType addressTLVType = 0
// addrVersionType is the TLV type of the address format version.
addrVersionType addressTLVType = 0

// addrAssetVersionType is the TLV type of the asset version.
addrAssetVersionType addressTLVType = 2

// addrAssetIDType is the TLV type of the asset ID.
addrAssetIDType addressTLVType = 2
addrAssetIDType addressTLVType = 4

// addrGroupKeyType is the TLV type of the group key of the asset.
addrGroupKeyType addressTLVType = 3
addrGroupKeyType addressTLVType = 5

// addrScriptKeyType is the TLV type of the script key for the asset.
addrScriptKeyType addressTLVType = 4
addrScriptKeyType addressTLVType = 6

// addrInternalKeyType is the TLV type of the internal key for the asset.
addrInternalKeyType addressTLVType = 6
addrInternalKeyType addressTLVType = 8

// addrTapscriptSiblingType is the TLV type of the tapscript sibling for
// the asset commitment.
addrTapscriptSiblingType addressTLVType = 7
addrTapscriptSiblingType addressTLVType = 9

// addrAmountType is the TLV type of the amount of the asset.
addrAmountType addressTLVType = 8
addrAmountType addressTLVType = 10

// addrProofCourierType is the TLV type of the proof courier address.
addrProofCourierAddrType addressTLVType = 10

// addrVersionType is the TLV type of the address's version.
addrVersionType addressTLVType = 12
addrProofCourierAddrType addressTLVType = 12
)

func newAddressVersionRecord(version *asset.Version) tlv.Record {
func newAddressVersionRecord(version *Version) tlv.Record {
return tlv.MakeStaticRecord(
addrVersionType, version, 1, VersionEncoder, VersionDecoder,
)
}

func newAddressAssetVersionRecord(version *asset.Version) tlv.Record {
return tlv.MakeStaticRecord(
addrAssetVersionType, version, 1, asset.VersionEncoder,
asset.VersionDecoder,
Expand Down Expand Up @@ -112,9 +118,3 @@ func newProofCourierAddrRecord(addr *url.URL) tlv.Record {
urlEncoder, urlDecoder,
)
}

func newVersionRecord(version *Version) tlv.Record {
return tlv.MakeStaticRecord(
addrVersionType, version, 1, VersionEncoder, VersionDecoder,
)
}
Loading

0 comments on commit 33f722e

Please sign in to comment.