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

Taproot support #195

Closed
wants to merge 30 commits into from
Closed
Show file tree
Hide file tree
Changes from 12 commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
93ea338
update with new btcsuite
louisinger May 24, 2022
e1c9105
taproot pkg
louisinger May 25, 2022
7505a73
taproot_test from txscript
louisinger May 25, 2022
0c80e19
blech32m (blech32 pkg)
louisinger May 25, 2022
b50697f
update blech32
louisinger May 25, 2022
cafcb96
payment and sighash
louisinger May 25, 2022
4a02155
improve address pkg support + testing (payment_test)
louisinger May 26, 2022
58f1e08
witnessHashV1
louisinger May 31, 2022
5e07f57
bech32m encode segwitv1 addr
louisinger May 31, 2022
c0354b2
witnessHashV1 input/output type
louisinger May 31, 2022
376b12c
taproot integration testing
louisinger May 31, 2022
450adb1
add new elements opcodes
louisinger May 31, 2022
dc6309c
go mod tidy
louisinger May 31, 2022
6489122
cleaning go.mod
louisinger May 31, 2022
abfbdd0
taproot address test cases
louisinger Jun 8, 2022
6087694
fix FromConfidential for taproot addresses
louisinger Jun 8, 2022
5658e5c
handle panics in p2tr + add failing test cases
louisinger Jun 8, 2022
fb4f143
import witnesshash v1 fixtures and fix sighash
louisinger Jun 9, 2022
95bde0e
improve serialize functions
louisinger Jun 9, 2022
a024a66
comments and cleaning
louisinger Jun 9, 2022
376dce9
compute script in P2TR payments
louisinger Jun 9, 2022
c1b3997
use btcd 0.23.1
louisinger Jun 9, 2022
c51e74c
go 1.17 in CI
louisinger Jun 9, 2022
ab56c36
add go clean
louisinger Jun 9, 2022
e9378b0
Revert "add go clean"
louisinger Jun 9, 2022
1997e17
mutate pset_test.go
louisinger Jun 9, 2022
411d466
skip TestBroadcastBlindedSwapTx
louisinger Jun 9, 2022
2021c55
Revert "skip TestBroadcastBlindedSwapTx"
louisinger Jun 9, 2022
6c05813
go.mod upgrade
louisinger Jun 10, 2022
d94f09c
use btcec/v2 v2.1.3
louisinger Jun 10, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
106 changes: 80 additions & 26 deletions address/address.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@ import (
"fmt"
"strings"

"github.com/btcsuite/btcd/btcutil/base58"
"github.com/btcsuite/btcd/btcutil/bech32"
"github.com/btcsuite/btcd/txscript"
"github.com/btcsuite/btcutil/base58"
"github.com/btcsuite/btcutil/bech32"
"github.com/vulpemventures/go-elements/blech32"
"github.com/vulpemventures/go-elements/network"
"golang.org/x/crypto/ripemd160"
Expand All @@ -28,12 +28,15 @@ const (
P2Wsh
ConfidentialP2Wpkh
ConfidentialP2Wsh
P2TR
ConfidentialP2TR

P2PkhScript = 1
P2ShScript = 2
P2MultiSigScript = 3
P2WpkhScript = 4
P2WshScript = 5
P2TRScript = 6
)

// Base58 type defines the structure of a legacy or wrapped segwit address
Expand Down Expand Up @@ -161,9 +164,22 @@ func ToBech32(bc *Bech32) (string, error) {
combined := make([]byte, len(converted)+1)
combined[0] = bc.Version
copy(combined[1:], converted)
bech, err := bech32.Encode(bc.Prefix, combined)
if err != nil {
return "", err

var bech string

switch bc.Version {
case 0:
bech, err = bech32.Encode(bc.Prefix, combined)
if err != nil {
return "", err
}
case 1:
bech, err = bech32.EncodeM(bc.Prefix, combined)
if err != nil {
return "", err
}
default:
return "", errors.New("unsupported witness version")
}

return bech, nil
Expand Down Expand Up @@ -283,7 +299,12 @@ func ToBlech32(bl *Blech32) (string, error) {
combined := make([]byte, len(converted)+1)
combined[0] = bl.Version
copy(combined[1:], converted)
blech32Addr, err := blech32.Encode(bl.Prefix, combined)
enc, err := blech32.EncodingTypeFromSegwitVersion(bl.Version)
if err != nil {
return "", err
}

blech32Addr, err := blech32.Encode(bl.Prefix, combined, enc)
if err != nil {
return "", err
}
Expand Down Expand Up @@ -482,22 +503,34 @@ func ToOutputScript(address string) ([]byte, error) {
AddData(scriptHash).
AddOp(txscript.OP_EQUAL).
Script()
case P2Wpkh, P2Wsh:
case P2Wpkh, P2Wsh, P2TR:
fromBech32, err := FromBech32(address)
if err != nil {
return nil, err
}

versionOpcode := byte(txscript.OP_0)
if fromBech32.Version == 1 {
versionOpcode = txscript.OP_1
}

return txscript.NewScriptBuilder().
AddOp(txscript.OP_0).
AddOp(versionOpcode).
AddData(fromBech32.Program).
Script()
case ConfidentialP2Wpkh, ConfidentialP2Wsh:
case ConfidentialP2Wpkh, ConfidentialP2Wsh, ConfidentialP2TR:
fromBlech32, err := FromBlech32(address)
if err != nil {
return nil, err
}

versionOpcode := byte(txscript.OP_0)
if fromBlech32.Version == 1 {
versionOpcode = txscript.OP_1
}

return txscript.NewScriptBuilder().
AddOp(txscript.OP_0).
AddOp(versionOpcode).
AddData(fromBlech32.Program).
Script()
default:
Expand All @@ -508,11 +541,13 @@ func ToOutputScript(address string) ([]byte, error) {
// GetScriptType returns the type of the given script (p2pkh, p2sh, etc.)
func GetScriptType(script []byte) int {
switch script[0] {
case txscript.OP_0:
case txscript.OP_0: // segwit v0
if len(script[2:]) == 20 {
return P2WpkhScript
}
return P2WshScript
case txscript.OP_1: // segwit v1 (taproot)
return P2TRScript
case txscript.OP_HASH160:
return P2ShScript
case txscript.OP_DUP:
Expand Down Expand Up @@ -548,7 +583,8 @@ func IsConfidential(address string) (bool, error) {
isConfidential := (addressType == ConfidentialP2Pkh ||
addressType == ConfidentialP2Sh ||
addressType == ConfidentialP2Wpkh ||
addressType == ConfidentialP2Wsh)
addressType == ConfidentialP2Wsh ||
addressType == ConfidentialP2TR)

return isConfidential, nil
}
Expand All @@ -562,14 +598,23 @@ func decodeBlech32(address string, net network.Network) (int, error) {
if err != nil {
return 0, err
}
switch len(fromBlech32.Program) {
case 20:
return ConfidentialP2Wpkh, nil
case 32:
return ConfidentialP2Wsh, nil
default:
return 0, errors.New("invalid program Length")

if fromBlech32.Version == 0 {
switch len(fromBlech32.Program) {
case 20:
return ConfidentialP2Wpkh, nil
case 32:
return ConfidentialP2Wsh, nil
default:
return 0, errors.New("invalid program Length")
}
}

if fromBlech32.Version == 1 {
return ConfidentialP2TR, nil
}

return 0, errors.New("invalid segwit version")
}

func isBech32(address string, net network.Network) bool {
Expand All @@ -581,14 +626,23 @@ func decodeBech32(address string, net network.Network) (int, error) {
if err != nil {
return 0, err
}
switch len(fromBech32.Program) {
case 20:
return P2Wpkh, nil
case 32:
return P2Wsh, nil
default:
return 0, errors.New("invalid program Length")

if fromBech32.Version == 0 {
switch len(fromBech32.Program) {
case 20:
return P2Wpkh, nil
case 32:
return P2Wsh, nil
default:
return 0, errors.New("invalid program Length")
}
}

if fromBech32.Version == 1 {
return P2TR, nil
}

return 0, errors.New("invalid segwit version")
}

func decodeBase58(address string, net network.Network) (int, error) {
Expand Down
50 changes: 49 additions & 1 deletion address/opcode.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,52 @@ package address

import "github.com/btcsuite/btcd/txscript"

// elements tapscript opcodes
const (
OP_SHA256INITIALIZE = 0xc4
OP_SHA256UPDATE = 0xc5
OP_SHA256FINALIZE = 0xc6

// Introspection opcodes
// inputs
OP_INSPECTINPUTOUTPOINT = 0xc7
OP_INSPECTINPUTASSET = 0xc8
OP_INSPECTINPUTVALUE = 0xc9
OP_INSPECTINPUTSCRIPTPUBKEY = 0xca
OP_INSPECTINPUTSEQUENCE = 0xcb
OP_INSPECTINPUTISSUANCE = 0xcc
OP_PUSHCURRENTINPUTINDEX = 0xcd

// outputs
OP_INSPECTOUTPUTASSET = 0xce
OP_INSPECTOUTPUTVALUE = 0xcf
OP_INSPECTOUTPUTNONCE = 0xd0
OP_INSPECTOUTPUTSCRIPTPUBKEY = 0xd1

// transaction
OP_INSPECTVERSION = 0xd2
OP_INSPECTLOCKTIME = 0xd3
OP_INSPECTNUMINPUTS = 0xd4
OP_INSPECTNUMOUTPUTS = 0xd5
OP_TXWEIGHT = 0xd6

// Arithmetic opcodes
OP_ADD64 = 0xd7
OP_SUB64 = 0xd8
OP_MUL64 = 0xd9
OP_DIV64 = 0xda
OP_NEG64 = 0xdb
OP_LESSTHAN64 = 0xdc
OP_LESSTHANOREQUAL64 = 0xdd
OP_GREATERTHAN64 = 0xde
OP_GREATERTHANOREQUAL64 = 0xdf

// Conversion opcodes
OP_SCRIPTNUMTOLE64 = 0xe0
OP_LE64TOSCRIPTNUM = 0xe1
OP_LE32TOLE64 = 0xe2
)

// opcodeArray holds details about all possible opcodes such as how many bytes
// the Opcode and any associated Data should take, its human-readable Name, and
// the handler function.
Expand Down Expand Up @@ -209,8 +255,10 @@ var opcodeArray = [256]Opcode{
txscript.OP_NOP9: {txscript.OP_NOP9, "OP_NOP9", 1},
txscript.OP_NOP10: {txscript.OP_NOP10, "OP_NOP10", 1},

// taproot update
txscript.OP_CHECKSIGADD: {txscript.OP_CHECKSIGADD, "OP_CHECKSIGADD", 1},

// Undefined opcodes.
txscript.OP_UNKNOWN186: {txscript.OP_UNKNOWN186, "OP_UNKNOWN186", 1},
txscript.OP_UNKNOWN187: {txscript.OP_UNKNOWN187, "OP_UNKNOWN187", 1},
txscript.OP_UNKNOWN188: {txscript.OP_UNKNOWN188, "OP_UNKNOWN188", 1},
txscript.OP_UNKNOWN189: {txscript.OP_UNKNOWN189, "OP_UNKNOWN189", 1},
Expand Down