diff --git a/address/address.go b/address/address.go index 6d6fdacda..d38c5b25b 100644 --- a/address/address.go +++ b/address/address.go @@ -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 @@ -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 ) @@ -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, @@ -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 { @@ -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(), @@ -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 { @@ -337,7 +331,6 @@ func (a *Tap) EncodeRecords() []tlv.Record { records = append( records, newProofCourierAddrRecord(&a.ProofCourierAddr), ) - records = append(records, newVersionRecord(&a.Version)) return records } @@ -346,7 +339,8 @@ 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), @@ -354,7 +348,6 @@ func (a *Tap) DecodeRecords() []tlv.Record { newAddressTapscriptSiblingRecord(&a.TapscriptSibling), newAddressAmountRecord(&a.Amount), newProofCourierAddrRecord(&a.ProofCourierAddr), - newVersionRecord(&a.Version), } } @@ -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) { diff --git a/address/address_test.go b/address/address_test.go index d39805920..be0b63cf5 100644 --- a/address/address_test.go +++ b/address/address_test.go @@ -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() @@ -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, ) } @@ -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 @@ -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, ) }, @@ -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, ) }, @@ -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, ) }, @@ -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, ) }, @@ -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, @@ -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 { @@ -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) diff --git a/address/book.go b/address/book.go index e8768d0b9..5f582140a 100644 --- a/address/book.go +++ b/address/book.go @@ -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) diff --git a/address/mock.go b/address/mock.go index 938249375..e0ebefee8 100644 --- a/address/mock.go +++ b/address/mock.go @@ -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, ) diff --git a/address/records.go b/address/records.go index 54c5f2518..d7b4086fd 100644 --- a/address/records.go +++ b/address/records.go @@ -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, @@ -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, - ) -} diff --git a/address/testdata/address_tlv_encoding_generated.json b/address/testdata/address_tlv_encoding_generated.json index c5536ab28..41880b42f 100644 --- a/address/testdata/address_tlv_encoding_generated.json +++ b/address/testdata/address_tlv_encoding_generated.json @@ -13,7 +13,7 @@ "amount": 5577006791947779410, "proof_courier_addr": "hashmail://rand.hashmail.proof.courier:443" }, - "expected": "taprt1qqqsqq3q0gupzcctkv6s83jndsazy0fu4m9e8lj47je589fgahe8kyxn36fsgggz5zh7k9jlpmpk3q9k3c9640v6m8rzl5dxn25e30psax35vgpwq78svggz5zh7k9jlpmpk3q9k3c9640v6m8rzl5dxn25e30psax35vgpwq78ssz0lf4jcygg8ln74yz32dpshx6rdv95kcw309aexzmny9e5xzumgd4skjmpwwpex7mmx9e3k7atjd9jhyw35xsescqgq6tnekq", + "expected": "taprt1qqqsqqspqqzzq73cz93shve4q0r9xmp6yg7netktj0l9ta9ngw2j3m0j0vgd8r5nqcss9g90avt97rkrdzqtdrst427e4kwx9lg6dx4fnz7rp6drgcszupu0pqss9g90avt97rkrdzqtdrst427e4kwx9lg6dx4fnz7rp6drgcszupu0pgyl7nt9sgss0l8a2gxz56rpwd5x6ctfdsaz7tmjv9hxgtngv9eksmtpd9kzuurjdahkvtnrda6hy6t9wgargdpn5zn5dz", "comment": "valid regtest address" }, { @@ -29,7 +29,7 @@ "amount": 3510942875414458836, "proof_courier_addr": "hashmail://rand.hashmail.proof.courier:443" }, - "expected": "tapsb1qqqsqq3q3t94z4pxzsja6cflmgvaacq22854c6fpm790gzzmc358q6u5dlkqgggz5zh7k9jlpmpk3q9k3c9640v6m8rzl5dxn25e30psax35vgpwq78svggz5zh7k9jlpmpk3q9k3c9640v6m8rzl5dxn25e30psax35vgpwq78ssz0lxzu4luvrc3cagz32dpshx6rdv95kcw309aexzmny9e5xzumgd4skjmpwwpex7mmx9e3k7atjd9jhyw35xsescqgqrmqdpv", + "expected": "tapsb1qqqsqqspqqzzpzkt292zv9p9m4snlksemmsq550ft35jrhu27sy9h3rgwp4egmlvqcss9g90avt97rkrdzqtdrst427e4kwx9lg6dx4fnz7rp6drgcszupu0pqss9g90avt97rkrdzqtdrst427e4kwx9lg6dx4fnz7rp6drgcszupu0pgyl7v9etlcc83r36sxz56rpwd5x6ctfdsaz7tmjv9hxgtngv9eksmtpd9kzuurjdahkvtnrda6hy6t9wgargdpnrzxc4w", "comment": "valid simnet address" }, { @@ -45,7 +45,7 @@ "amount": 2740103009342231109, "proof_courier_addr": "hashmail://rand.hashmail.proof.courier:443" }, - "expected": "taptb1qqqsqq3qvpzeew6dfe483wx9s4zl9lszdtfp00c04lhdtl678vehn3jcmhesgggz5zh7k9jlpmpk3q9k3c9640v6m8rzl5dxn25e30psax35vgpwq78svggz5zh7k9jlpmpk3q9k3c9640v6m8rzl5dxn25e30psax35vgpwq78ssz0lycrv626h62fy2z32dpshx6rdv95kcw309aexzmny9e5xzumgd4skjmpwwpex7mmx9e3k7atjd9jhyw35xsescqgqe3e6yp", + "expected": "taptb1qqqsqqspqqzzqcz9nja56nn20zuvtp297tlqy6kjz7lsltlw6hl4uwen08r93h0nqcss9g90avt97rkrdzqtdrst427e4kwx9lg6dx4fnz7rp6drgcszupu0pqss9g90avt97rkrdzqtdrst427e4kwx9lg6dx4fnz7rp6drgcszupu0pgyl7fsxe544055jg5xz56rpwd5x6ctfdsaz7tmjv9hxgtngv9eksmtpd9kzuurjdahkvtnrda6hy6t9wgargdpny8e5zg", "comment": "valid testnet address" }, { @@ -61,7 +61,7 @@ "amount": 545291762129038907, "proof_courier_addr": "hashmail://rand.hashmail.proof.courier:443" }, - "expected": "tapbc1qqqsqq3q7trsuynpkaslpxzfnyv2eakv7xxhm88he447pj2qvv8svsatsvkqgggz5zh7k9jlpmpk3q9k3c9640v6m8rzl5dxn25e30psax35vgpwq78svggz5zh7k9jlpmpk3q9k3c9640v6m8rzl5dxn25e30psax35vgpwq78ssz0lq7g58al55hhrkz32dpshx6rdv95kcw309aexzmny9e5xzumgd4skjmpwwpex7mmx9e3k7atjd9jhyw35xsescqgqkmlk2r", + "expected": "tapbc1qqqsqqspqqzzpuk8pcfxrdmp7zvynxgc4nmveuvd0kw00nttury5qcc0qep6hqevqcss9g90avt97rkrdzqtdrst427e4kwx9lg6dx4fnz7rp6drgcszupu0pqss9g90avt97rkrdzqtdrst427e4kwx9lg6dx4fnz7rp6drgcszupu0pgyl7pu3g0mlff0w8vxz56rpwd5x6ctfdsaz7tmjv9hxgtngv9eksmtpd9kzuurjdahkvtnrda6hy6t9wgargdpnlhg0u8", "comment": "valid mainnet address" }, { @@ -77,7 +77,7 @@ "amount": 1, "proof_courier_addr": "hashmail://rand.hashmail.proof.courier:443" }, - "expected": "taptb1qqqsqq3q0uaffvcy3m9uunetz6rw9hufhhjj6h4drtksz8m4lfjh3h9tpqusxggr7vkj8xgy6xka4eeg6xgh499ur5sy2kcjkfg6jg3dqd09q99f7avsgggz5zh7k9jlpmpk3q9k3c9640v6m8rzl5dxn25e30psax35vgpwq78svggz5zh7k9jlpmpk3q9k3c9640v6m8rzl5dxn25e30psax35vgpwq78ssqgppg4xsctndpkkz6tv8ghj7unpdejzu6rpwd5x6ctfdsh8qun0danzucm0w4exjetj8g6rgvcvqyqq7z78w5", + "expected": "taptb1qqqsqqspqqzzqle6jjesfrktee8jk95xut0cn00994026xhdqy0ht7n90rw2kzpeq5ss8uedywvsf5ddmtnj35v3022tc8fqg4d39vj34y3z6q672q22na6eqcss9g90avt97rkrdzqtdrst427e4kwx9lg6dx4fnz7rp6drgcszupu0pqss9g90avt97rkrdzqtdrst427e4kwx9lg6dx4fnz7rp6drgcszupu0pgqszrp2dpshx6rdv95kcw309aexzmny9e5xzumgd4skjmpwwpex7mmx9e3k7atjd9jhyw35xseskkqklz", "comment": "signet group collectible" }, { @@ -93,7 +93,7 @@ "amount": 1, "proof_courier_addr": "hashmail://rand.hashmail.proof.courier:443" }, - "expected": "tapsb1qqqsqq3q0ksqh36tl6terqrl5gxmampzvdyfqnntl2xpp26rfy3rd8jdgarsgggz5zh7k9jlpmpk3q9k3c9640v6m8rzl5dxn25e30psax35vgpwq78svggz5zh7k9jlpmpk3q9k3c9640v6m8rzl5dxn25e30psax35vgpwq78ssqgppg4xsctndpkkz6tv8ghj7unpdejzu6rpwd5x6ctfdsh8qun0danzucm0w4exjetj8g6rgvcvqyqqt6swda", + "expected": "tapsb1qqqsqqspqqzzqldqp0r5hl5hjxq8lgsdhmkzyc6gjp8xh75vzz45xjfzx60y6368qcss9g90avt97rkrdzqtdrst427e4kwx9lg6dx4fnz7rp6drgcszupu0pqss9g90avt97rkrdzqtdrst427e4kwx9lg6dx4fnz7rp6drgcszupu0pgqszrp2dpshx6rdv95kcw309aexzmny9e5xzumgd4skjmpwwpex7mmx9e3k7atjd9jhyw35xses3sew7m", "comment": "simnet collectible" }, { @@ -109,7 +109,7 @@ "amount": 1, "proof_courier_addr": "hashmail://rand.hashmail.proof.courier:443" }, - "expected": "tapsb1qqqsqq3qkcpam2h6cwmz200z8tspjd03pzlwjcmrah0hw3tvpcjw66n8v58sgggz5zh7k9jlpmpk3q9k3c9640v6m8rzl5dxn25e30psax35vgpwq78svggz5zh7k9jlpmpk3q9k3c9640v6m8rzl5dxn25e30psax35vgpwq78sw9gqcqfxumm5ypsjqanpd35kggrnvdexjur5pqqszz32dpshx6rdv95kcw309aexzmny9e5xzumgd4skjmpwwpex7mmx9e3k7atjd9jhyw35xsescqgqsc83mh", + "expected": "tapsb1qqqsqqspqqzzpdsrmk404saky577ywhqry6lzz97a93k8mwlwazkcr3ya44xweg0qcss9g90avt97rkrdzqtdrst427e4kwx9lg6dx4fnz7rp6drgcszupu0pqss9g90avt97rkrdzqtdrst427e4kwx9lg6dx4fnz7rp6drgcszupu0py2spsqjdehhggrpypmxzmrfvss8xcmjd9c8gzspqyxz56rpwd5x6ctfdsaz7tmjv9hxgtngv9eksmtpd9kzuurjdahkvtnrda6hy6t9wgargdpng4k730", "comment": "simnet collectible with sibling" } ], diff --git a/tapdb/addrs.go b/tapdb/addrs.go index fd039777a..3cd671c34 100644 --- a/tapdb/addrs.go +++ b/tapdb/addrs.go @@ -267,7 +267,8 @@ func (t *TapAddressBook) InsertAddrs(ctx context.Context, ) _, err = db.InsertAddr(ctx, NewAddr{ - Version: int16(addr.AssetVersion), + Version: int16(addr.Version), + AssetVersion: int16(addr.AssetVersion), GenesisAssetID: genAssetID, GroupKey: groupKeyBytes, ScriptKeyID: scriptKeyID, @@ -432,15 +433,15 @@ func (t *TapAddressBook) QueryAddrs(ctx context.Context, } tapAddr, err := address.New( - assetGenesis, groupKey, groupSig, *scriptKey, + address.Version(addr.Version), assetGenesis, + groupKey, groupSig, *scriptKey, *internalKey, uint64(addr.Amount), - tapscriptSibling, t.params, - *proofCourierAddr, + tapscriptSibling, t.params, *proofCourierAddr, ) if err != nil { return fmt.Errorf("unable to make addr: %w", err) } - tapAddr.AssetVersion = asset.Version(addr.Version) + tapAddr.AssetVersion = asset.Version(addr.AssetVersion) addrs = append(addrs, address.AddrWithKeyInfo{ Tap: tapAddr, @@ -578,14 +579,14 @@ func fetchAddr(ctx context.Context, db AddrBook, params *address.ChainParams, } tapAddr, err := address.New( - genesis, groupKey, groupSig, *scriptKey, *internalKey, - uint64(dbAddr.Amount), tapscriptSibling, params, - *proofCourierAddr, + address.Version(dbAddr.Version), genesis, groupKey, + groupSig, *scriptKey, *internalKey, uint64(dbAddr.Amount), + tapscriptSibling, params, *proofCourierAddr, ) if err != nil { return nil, fmt.Errorf("unable to make addr: %w", err) } - tapAddr.AssetVersion = asset.Version(dbAddr.Version) + tapAddr.AssetVersion = asset.Version(dbAddr.AssetVersion) return &address.AddrWithKeyInfo{ Tap: tapAddr, diff --git a/tapdb/sqlc/addrs.sql.go b/tapdb/sqlc/addrs.sql.go index f9ae40fcf..f79f618c6 100644 --- a/tapdb/sqlc/addrs.sql.go +++ b/tapdb/sqlc/addrs.sql.go @@ -13,8 +13,9 @@ import ( const fetchAddrByTaprootOutputKey = `-- name: FetchAddrByTaprootOutputKey :one SELECT - version, genesis_asset_id, group_key, tapscript_sibling, taproot_output_key, - amount, asset_type, creation_time, managed_from, proof_courier_addr, + version, asset_version, genesis_asset_id, group_key, tapscript_sibling, + taproot_output_key, amount, asset_type, creation_time, managed_from, + proof_courier_addr, script_keys.tweaked_script_key, script_keys.tweak AS script_key_tweak, raw_script_keys.raw_key as raw_script_key, @@ -35,6 +36,7 @@ WHERE taproot_output_key = $1 type FetchAddrByTaprootOutputKeyRow struct { Version int16 + AssetVersion int16 GenesisAssetID int32 GroupKey []byte TapscriptSibling []byte @@ -59,6 +61,7 @@ func (q *Queries) FetchAddrByTaprootOutputKey(ctx context.Context, taprootOutput var i FetchAddrByTaprootOutputKeyRow err := row.Scan( &i.Version, + &i.AssetVersion, &i.GenesisAssetID, &i.GroupKey, &i.TapscriptSibling, @@ -132,8 +135,9 @@ func (q *Queries) FetchAddrEvent(ctx context.Context, id int32) (FetchAddrEventR const fetchAddrs = `-- name: FetchAddrs :many SELECT - version, genesis_asset_id, group_key, tapscript_sibling, taproot_output_key, - amount, asset_type, creation_time, managed_from, proof_courier_addr, + version, asset_version, genesis_asset_id, group_key, tapscript_sibling, + taproot_output_key, amount, asset_type, creation_time, managed_from, + proof_courier_addr, script_keys.tweaked_script_key, script_keys.tweak AS script_key_tweak, raw_script_keys.raw_key AS raw_script_key, @@ -167,6 +171,7 @@ type FetchAddrsParams struct { type FetchAddrsRow struct { Version int16 + AssetVersion int16 GenesisAssetID int32 GroupKey []byte TapscriptSibling []byte @@ -203,6 +208,7 @@ func (q *Queries) FetchAddrs(ctx context.Context, arg FetchAddrsParams) ([]Fetch var i FetchAddrsRow if err := rows.Scan( &i.Version, + &i.AssetVersion, &i.GenesisAssetID, &i.GroupKey, &i.TapscriptSibling, @@ -236,14 +242,15 @@ func (q *Queries) FetchAddrs(ctx context.Context, arg FetchAddrsParams) ([]Fetch const insertAddr = `-- name: InsertAddr :one INSERT INTO addrs ( - version, genesis_asset_id, group_key, script_key_id, taproot_key_id, - tapscript_sibling, taproot_output_key, amount, asset_type, creation_time, - proof_courier_addr -) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11) RETURNING id + version, asset_version, genesis_asset_id, group_key, script_key_id, + taproot_key_id, tapscript_sibling, taproot_output_key, amount, asset_type, + creation_time, proof_courier_addr +) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12) RETURNING id ` type InsertAddrParams struct { Version int16 + AssetVersion int16 GenesisAssetID int32 GroupKey []byte ScriptKeyID int32 @@ -259,6 +266,7 @@ type InsertAddrParams struct { func (q *Queries) InsertAddr(ctx context.Context, arg InsertAddrParams) (int32, error) { row := q.db.QueryRowContext(ctx, insertAddr, arg.Version, + arg.AssetVersion, arg.GenesisAssetID, arg.GroupKey, arg.ScriptKeyID, diff --git a/tapdb/sqlc/migrations/000003_addrs.up.sql b/tapdb/sqlc/migrations/000003_addrs.up.sql index 0a09de4db..6483c0e96 100644 --- a/tapdb/sqlc/migrations/000003_addrs.up.sql +++ b/tapdb/sqlc/migrations/000003_addrs.up.sql @@ -4,9 +4,12 @@ CREATE TABLE IF NOT EXISTS addrs ( id INTEGER PRIMARY KEY, - -- version is the Taproot Asset script version this address support. + -- version is the version of the Taproot Asset address format. version SMALLINT NOT NULL, + -- asset_version is the asset version this address supports. + asset_version SMALLINT NOT NULL, + -- genesis_asset_id points to the asset genesis of the asset we want to -- send/recv. genesis_asset_id INTEGER NOT NULL REFERENCES genesis_assets(gen_asset_id), diff --git a/tapdb/sqlc/models.go b/tapdb/sqlc/models.go index d185c7179..57e577af6 100644 --- a/tapdb/sqlc/models.go +++ b/tapdb/sqlc/models.go @@ -12,6 +12,7 @@ import ( type Addr struct { ID int32 Version int16 + AssetVersion int16 GenesisAssetID int32 GroupKey []byte ScriptKeyID int32 diff --git a/tapdb/sqlc/queries/addrs.sql b/tapdb/sqlc/queries/addrs.sql index c8be6a21d..4c89778ba 100644 --- a/tapdb/sqlc/queries/addrs.sql +++ b/tapdb/sqlc/queries/addrs.sql @@ -1,14 +1,15 @@ -- name: InsertAddr :one INSERT INTO addrs ( - version, genesis_asset_id, group_key, script_key_id, taproot_key_id, - tapscript_sibling, taproot_output_key, amount, asset_type, creation_time, - proof_courier_addr -) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11) RETURNING id; + version, asset_version, genesis_asset_id, group_key, script_key_id, + taproot_key_id, tapscript_sibling, taproot_output_key, amount, asset_type, + creation_time, proof_courier_addr +) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12) RETURNING id; -- name: FetchAddrs :many SELECT - version, genesis_asset_id, group_key, tapscript_sibling, taproot_output_key, - amount, asset_type, creation_time, managed_from, proof_courier_addr, + version, asset_version, genesis_asset_id, group_key, tapscript_sibling, + taproot_output_key, amount, asset_type, creation_time, managed_from, + proof_courier_addr, script_keys.tweaked_script_key, script_keys.tweak AS script_key_tweak, raw_script_keys.raw_key AS raw_script_key, @@ -33,8 +34,9 @@ LIMIT @num_limit OFFSET @num_offset; -- name: FetchAddrByTaprootOutputKey :one SELECT - version, genesis_asset_id, group_key, tapscript_sibling, taproot_output_key, - amount, asset_type, creation_time, managed_from, proof_courier_addr, + version, asset_version, genesis_asset_id, group_key, tapscript_sibling, + taproot_output_key, amount, asset_type, creation_time, managed_from, + proof_courier_addr, script_keys.tweaked_script_key, script_keys.tweak AS script_key_tweak, raw_script_keys.raw_key as raw_script_key, diff --git a/tapgarden/custodian_test.go b/tapgarden/custodian_test.go index 3e49db9ac..795896342 100644 --- a/tapgarden/custodian_test.go +++ b/tapgarden/custodian_test.go @@ -319,7 +319,7 @@ func mustMakeAddr(t *testing.T, var p btcec.PublicKey proofCourierAddr := address.RandProofCourierAddr(t) addr, err := address.New( - gen, groupKey, groupSig, scriptKey, + address.V0, gen, groupKey, groupSig, scriptKey, p, 1, nil, &address.TestNet3Tap, proofCourierAddr, ) require.NoError(t, err) diff --git a/tapscript/send_test.go b/tapscript/send_test.go index 5e7e0d23f..942346d40 100644 --- a/tapscript/send_test.go +++ b/tapscript/send_test.go @@ -127,18 +127,19 @@ func initSpendScenario(t *testing.T) spendData { proofCourierAddr := address.RandProofCourierAddr(t) address1, err := address.New( - state.genesis1, nil, nil, state.receiverPubKey, - state.receiverPubKey, state.normalAmt1, nil, &address.MainNetTap, - proofCourierAddr, + address.V0, state.genesis1, nil, nil, state.receiverPubKey, + state.receiverPubKey, state.normalAmt1, nil, + &address.MainNetTap, proofCourierAddr, ) require.NoError(t, err) state.address1 = *address1 state.address1StateKey = state.address1.AssetCommitmentKey() address1CollectGroup, err := address.New( - state.genesis1collect, &state.groupKey.GroupPubKey, - &state.groupKey.Sig, state.receiverPubKey, state.receiverPubKey, - state.collectAmt, nil, &address.TestNet3Tap, proofCourierAddr, + address.V0, state.genesis1collect, &state.groupKey.GroupPubKey, + &state.groupKey.Sig, state.receiverPubKey, + state.receiverPubKey, state.collectAmt, nil, + &address.TestNet3Tap, proofCourierAddr, ) require.NoError(t, err) state.address1CollectGroup = *address1CollectGroup @@ -146,7 +147,7 @@ func initSpendScenario(t *testing.T) spendData { AssetCommitmentKey() address2, err := address.New( - state.genesis1, nil, nil, state.receiverPubKey, + address.V0, state.genesis1, nil, nil, state.receiverPubKey, state.receiverPubKey, state.normalAmt2, nil, &address.MainNetTap, proofCourierAddr, ) @@ -2021,9 +2022,10 @@ var addressValidInputTestCases = []addressValidInputTestCase{{ state := initSpendScenario(t) address1testnet, err := address.New( - state.genesis1, nil, nil, state.receiverPubKey, - state.receiverPubKey, state.normalAmt1, nil, - &address.TestNet3Tap, address.RandProofCourierAddr(t), + address.V0, state.genesis1, nil, nil, + state.receiverPubKey, state.receiverPubKey, + state.normalAmt1, nil, &address.TestNet3Tap, + address.RandProofCourierAddr(t), ) require.NoError(t, err) @@ -2094,8 +2096,8 @@ func TestPayToAddrScript(t *testing.T) { // Create an address for receiving the 2 units and make sure it matches // the script above. addr1, err := address.New( - gen, nil, nil, *recipientScriptKey.PubKey, *internalKey, - sendAmt, nil, &address.RegressionNetTap, + address.V0, gen, nil, nil, *recipientScriptKey.PubKey, + *internalKey, sendAmt, nil, &address.RegressionNetTap, address.RandProofCourierAddr(t), ) require.NoError(t, err) @@ -2111,8 +2113,8 @@ func TestPayToAddrScript(t *testing.T) { []byte("not a valid script"), )) addr2, err := address.New( - gen, nil, nil, *recipientScriptKey.PubKey, *internalKey, - sendAmt, sibling, &address.RegressionNetTap, + address.V0, gen, nil, nil, *recipientScriptKey.PubKey, + *internalKey, sendAmt, sibling, &address.RegressionNetTap, address.RandProofCourierAddr(t), ) require.NoError(t, err)