Skip to content

Commit ab50d3d

Browse files
author
shadowy-pycoder
committed
Added creation of taproot addresses
1 parent f228c51 commit ab50d3d

File tree

2 files changed

+63
-15
lines changed

2 files changed

+63
-15
lines changed

bmt/main.go

Lines changed: 48 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -622,7 +622,7 @@ func (k *PrivateKey) ToWif(uncompressed bool) (*string, error) {
622622
//
623623
// If both parameters are nil generates a random wallet
624624
func CreateNewWallet(raw *big.Int, wif *string) (*Wallet, error) {
625-
var nestedAddress, nativeAddress string
625+
var nestedAddress, nativeAddress, taprootAddress string
626626
privKey, err := NewPrivateKey(raw, wif)
627627
if err != nil {
628628
return nil, err
@@ -636,13 +636,15 @@ func CreateNewWallet(raw *big.Int, wif *string) (*Wallet, error) {
636636
if !privKey.Uncompressed {
637637
nestedAddress = createNestedSegwit(pubKey)
638638
nativeAddress = createNativeSegwit(pubKey)
639+
taprootAddress = createTaproot(createTweakedPubKey(rawPubKey))
639640
}
640641
return &Wallet{PrivKey: privKey,
641642
RawPubKey: rawPubKey,
642643
PubKey: hex.EncodeToString(pubKey),
643644
Legacy: legacyAddress,
644645
Nested: nestedAddress,
645-
Native: nativeAddress}, nil
646+
Native: nativeAddress,
647+
Taproot: taprootAddress}, nil
646648
}
647649

648650
type Wallet struct {
@@ -652,6 +654,7 @@ type Wallet struct {
652654
Legacy string
653655
Nested string
654656
Native string
657+
Taproot string
655658
}
656659

657660
// String returns a formatted string representation of the Wallet.
@@ -670,7 +673,8 @@ Public Key (HEX Compressed): %s
670673
Legacy Address: %s
671674
Nested SegWit Address: %s
672675
Native SegWit Address: %s
673-
`, w.PrivKey.Raw, *w.PrivKey.Wif, w.RawPubKey, w.PubKey, w.Legacy, w.Nested, w.Native)
676+
Taproot Address: %s
677+
`, w.PrivKey.Raw, *w.PrivKey.Wif, w.RawPubKey, w.PubKey, w.Legacy, w.Nested, w.Native, w.Taproot)
674678
}
675679

676680
// NewInt converts a hexadecimal string to a big.Int pointer.
@@ -832,6 +836,32 @@ func createPubKey(rawPubKey *Point, uncompressed bool) []byte {
832836
return buf[:33]
833837
}
834838

839+
func calculateTweak(rawPubKey *Point) *big.Int {
840+
var tweak big.Int
841+
buf := make([]byte, 32)
842+
h1 := sha256.New()
843+
h2 := sha256.New()
844+
h1.Write([]byte("TapTweak"))
845+
h2.Write(joinBytes([][]byte{h1.Sum(nil), h1.Sum(nil), rawPubKey.X.FillBytes(buf)}...))
846+
tweak.SetBytes(h2.Sum(nil))
847+
return &tweak
848+
}
849+
850+
func createTweakedPubKey(rawPubKey *Point) []byte {
851+
var q JacobianPoint
852+
tweak := calculateTweak(rawPubKey)
853+
p := &Point{X: new(big.Int).Set(rawPubKey.X), Y: new(big.Int).Set(rawPubKey.Y)}
854+
if IsOdd(p.Y) {
855+
p.Y.Sub(Secp256k1.PCurve, p.Y)
856+
}
857+
q.Add(p.ToJacobian(), q.Mul(tweak, nil))
858+
qa := q.ToAffine()
859+
if IsOdd(qa.Y) {
860+
qa.Y.Sub(Secp256k1.PCurve, qa.Y)
861+
}
862+
return createPubKey(qa, false)[1:]
863+
}
864+
835865
// checkSum calculates the checksum of the input byte slice using DoubleSHA256 and returns the first 4 bytes.
836866
//
837867
// Parameters:
@@ -893,6 +923,21 @@ func createNativeSegwit(pubKey []byte) string {
893923
return addr
894924
}
895925

926+
func createTaproot(pubKey []byte) string {
927+
converted, err := bech32.ConvertBits(pubKey, 8, 5, true)
928+
if err != nil {
929+
panic(err)
930+
}
931+
combined := make([]byte, len(converted)+1)
932+
combined[0] = byte(1)
933+
copy(combined[1:], converted)
934+
addr, err := bech32.EncodeM("bc", combined)
935+
if err != nil {
936+
panic(err)
937+
}
938+
return addr
939+
}
940+
896941
// varInt generates a variable-length integer in bytes based on the input length.
897942
//
898943
// Parameters:

bmt/main_test.go

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -79,10 +79,11 @@ func TestCreateNewWalletFromRawPrivateKey(t *testing.T) {
7979
X: NewInt("e4ab48ce61667f57bb9ca0f31b9bca94981303004d3802b1c11faa9343a820ba"),
8080
Y: NewInt("17d5acd0ade3141bdccab4689a82151e638a70a56c1b4d38788e77c76e414dd3"),
8181
},
82-
PubKey: "03e4ab48ce61667f57bb9ca0f31b9bca94981303004d3802b1c11faa9343a820ba",
83-
Legacy: "1LBdJkrB4nkWkLLdKSBAD2CPRrpSaYQW51",
84-
Nested: "39RBCbgESnqjHpapfvqVPfLCPGrvGKxpbC",
85-
Native: "bc1q6fkdkwv5p6mxdhyj2gxhgu2tp5np53g6g8u0t0",
82+
PubKey: "03e4ab48ce61667f57bb9ca0f31b9bca94981303004d3802b1c11faa9343a820ba",
83+
Legacy: "1LBdJkrB4nkWkLLdKSBAD2CPRrpSaYQW51",
84+
Nested: "39RBCbgESnqjHpapfvqVPfLCPGrvGKxpbC",
85+
Native: "bc1q6fkdkwv5p6mxdhyj2gxhgu2tp5np53g6g8u0t0",
86+
Taproot: "bc1puzp40apyn38h3nqhzzxk6tmxxwvd0jcegnk4k88qvxntstsfhyvq5nr3us",
8687
},
8788
},
8889
{
@@ -97,10 +98,11 @@ func TestCreateNewWalletFromRawPrivateKey(t *testing.T) {
9798
X: NewInt("e483d1df60d0c9e16035672dfb92d7ddac6858b5233d33bb04996ae6a23f0149"),
9899
Y: NewInt("d0fb3cafc082957fdd8934a9fa2b5fbf2fee701ca595da7bb79a95f0063a13c5"),
99100
},
100-
PubKey: "03e483d1df60d0c9e16035672dfb92d7ddac6858b5233d33bb04996ae6a23f0149",
101-
Legacy: "13KXYTfq5FRQj6T3t6ds6FYqCDymYMwdmC",
102-
Nested: "34GeUW8iPUkWdfQSWFvumAt5RGtxhp3KCG",
103-
Native: "bc1qr9cncqd8v5j9uv86pfprqlkuh7htp5uwu6x56m",
101+
PubKey: "03e483d1df60d0c9e16035672dfb92d7ddac6858b5233d33bb04996ae6a23f0149",
102+
Legacy: "13KXYTfq5FRQj6T3t6ds6FYqCDymYMwdmC",
103+
Nested: "34GeUW8iPUkWdfQSWFvumAt5RGtxhp3KCG",
104+
Native: "bc1qr9cncqd8v5j9uv86pfprqlkuh7htp5uwu6x56m",
105+
Taproot: "bc1ph4zg3xz7z0kvmdp9nne6kpyc8yk9rsweepa3g5se40zkqa7rvwvslkl8fd",
104106
},
105107
},
106108
}
@@ -140,10 +142,11 @@ func TestCreateNewWalletFromWifPrivateKey(t *testing.T) {
140142
X: NewInt("66fde8efb47bfe53be63cccd068996f3a1c9172f1c2f6bc345dff6c589daefc5"),
141143
Y: NewInt("379ab4aa30d3247cb6b7c327067bd8199ff7bec32205ef043d3c9239ec6765b7"),
142144
},
143-
PubKey: "0366fde8efb47bfe53be63cccd068996f3a1c9172f1c2f6bc345dff6c589daefc5",
144-
Legacy: "14VXJudstcvqpx56BPQFSYJ1K39KGc3twM",
145-
Nested: "32vwEU1Esvp1AywrYgrnziHCaigLTn5AKN",
146-
Native: "bc1qyex4xghj4rldkysse2hdpt0arphh78xhp28ze2",
145+
PubKey: "0366fde8efb47bfe53be63cccd068996f3a1c9172f1c2f6bc345dff6c589daefc5",
146+
Legacy: "14VXJudstcvqpx56BPQFSYJ1K39KGc3twM",
147+
Nested: "32vwEU1Esvp1AywrYgrnziHCaigLTn5AKN",
148+
Native: "bc1qyex4xghj4rldkysse2hdpt0arphh78xhp28ze2",
149+
Taproot: "bc1pss2mar9sv2nktnx8ujqrjd9ld7n0zn9swl7zup5pcl8shq9es4kqlgx6g3",
147150
},
148151
},
149152
{

0 commit comments

Comments
 (0)