Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

multi: add address version to database #509

Merged
merged 1 commit into from
Sep 20, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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