Convert P2PK script to P2PKH so that it is indexed together #73

This commit is contained in:
Martin Boehm 2018-10-12 11:51:48 +02:00
parent 1a4eec22a1
commit f579b97502
4 changed files with 103 additions and 20 deletions

2
Gopkg.lock generated
View File

@ -89,7 +89,7 @@
branch = "master"
name = "github.com/jakm/btcutil"
packages = [".","base58","bech32","chaincfg","txscript"]
revision = "90ef4c720a6c3b3f9974dd6a6c6c339906236c35"
revision = "83dfbb3d0b20916f89b36b95c6ca580e3a785856"
[[projects]]
branch = "master"

View File

@ -150,29 +150,22 @@ func isCashAddr(addr string) bool {
// outputScriptToAddresses converts ScriptPubKey to bitcoin addresses
func (p *BCashParser) outputScriptToAddresses(script []byte) ([]string, bool, error) {
// convert possible P2PK script to P2PK, which bchutil can process
var err error
script, err = txscript.ConvertP2PKtoP2PKH(script)
if err != nil {
return nil, false, err
}
a, err := bchutil.ExtractPkScriptAddrs(script, p.Params)
if err != nil {
// do not return unknown script type error as error
if err.Error() == "unknown script type" {
// try bitcoin parser to parse P2PK scripts - kind of hack as bchutil does not support pay-to-pubkey
_, addresses, _, err := txscript.ExtractPkScriptAddrs(script, p.Params)
if err == nil && len(addresses) == 1 {
// convert the address back to output script and back to get from bitcoin to bcash
s, err := p.addressToOutputScript(addresses[0].EncodeAddress())
if err == nil {
a, err = bchutil.ExtractPkScriptAddrs(s, p.Params)
if err != nil {
return []string{}, false, nil
}
}
} else {
// try OP_RETURN script
or := btc.TryParseOPReturn(script)
if or != "" {
return []string{or}, false, nil
}
return []string{}, false, nil
// try OP_RETURN script
or := btc.TryParseOPReturn(script)
if or != "" {
return []string{or}, false, nil
}
return []string{}, false, nil
} else {
return nil, false, err
}

View File

@ -56,7 +56,13 @@ func GetChainParams(chain string) *chaincfg.Params {
// GetAddrDescFromVout returns internal address representation (descriptor) of given transaction output
func (p *BitcoinParser) GetAddrDescFromVout(output *bchain.Vout) (bchain.AddressDescriptor, error) {
return hex.DecodeString(output.ScriptPubKey.Hex)
ad, err := hex.DecodeString(output.ScriptPubKey.Hex)
if err != nil {
return ad, err
}
// convert possible P2PK script to P2PKH
// so that all transactions by given public key are indexed together
return txscript.ConvertP2PKtoP2PKH(ad)
}
// GetAddrDescFromAddress returns internal address representation (descriptor) of given address

View File

@ -35,6 +35,12 @@ func Test_GetAddrDescFromAddress(t *testing.T) {
want: "76a914be027bf3eac907bd4ac8cb9c5293b6f37662722088ac",
wantErr: false,
},
{
name: "P2PKH from P2PK",
args: args{address: "1HY6bKYhFH7HF3F48ikvziPHLrEWPGwXcE"},
want: "76a914b563933904dceba5c234e978bea0e9eb8b7e721b88ac",
wantErr: false,
},
{
name: "P2SH",
args: args{address: "321x69Cb9HZLWwAWGiUBT1U81r1zPLnEjL"},
@ -71,6 +77,70 @@ func Test_GetAddrDescFromAddress(t *testing.T) {
}
}
func Test_GetAddrDescFromVout(t *testing.T) {
type args struct {
vout bchain.Vout
}
tests := []struct {
name string
args args
want string
wantErr bool
}{
{
name: "P2PKH",
args: args{vout: bchain.Vout{ScriptPubKey: bchain.ScriptPubKey{Hex: "76a914be027bf3eac907bd4ac8cb9c5293b6f37662722088ac"}}},
want: "76a914be027bf3eac907bd4ac8cb9c5293b6f37662722088ac",
wantErr: false,
},
{
name: "P2PK compressed 1P3rU1Nk1pmc2BiWC8dEy9bZa1ZbMp5jfg",
args: args{vout: bchain.Vout{ScriptPubKey: bchain.ScriptPubKey{Hex: "21020e46e79a2a8d12b9b5d12c7a91adb4e454edfae43c0a0cb805427d2ac7613fd9ac"}}},
want: "76a914f1dce4182fce875748c4986b240ff7d7bc3fffb088ac",
wantErr: false,
},
{
name: "P2PK uncompressed 1HY6bKYhFH7HF3F48ikvziPHLrEWPGwXcE",
args: args{vout: bchain.Vout{ScriptPubKey: bchain.ScriptPubKey{Hex: "41041057356b91bfd3efeff5fc0fa8b865faafafb67bd653c5da2cd16ce15c7b86db0e622c8e1e135f68918a23601eb49208c1ac72c7b64a4ee99c396cf788da16ccac"}}},
want: "76a914b563933904dceba5c234e978bea0e9eb8b7e721b88ac",
wantErr: false,
},
{
name: "P2SH",
args: args{vout: bchain.Vout{ScriptPubKey: bchain.ScriptPubKey{Hex: "a9140394b3cf9a44782c10105b93962daa8dba304d7f87"}}},
want: "a9140394b3cf9a44782c10105b93962daa8dba304d7f87",
wantErr: false,
},
{
name: "P2WPKH",
args: args{vout: bchain.Vout{ScriptPubKey: bchain.ScriptPubKey{Hex: "00141c12afc6b2602607fdbc209f2a053c54ecd2c673"}}},
want: "00141c12afc6b2602607fdbc209f2a053c54ecd2c673",
wantErr: false,
},
{
name: "P2WSH",
args: args{vout: bchain.Vout{ScriptPubKey: bchain.ScriptPubKey{Hex: "002003973a40ec94c0d10f6f6f0e7a62ba2044b7d19db6ff2bf60651e17fb29d8d29"}}},
want: "002003973a40ec94c0d10f6f6f0e7a62ba2044b7d19db6ff2bf60651e17fb29d8d29",
wantErr: false,
},
}
parser := NewBitcoinParser(GetChainParams("main"), &Configuration{})
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := parser.GetAddrDescFromVout(&tt.args.vout)
if (err != nil) != tt.wantErr {
t.Errorf("GetAddrDescFromVout() error = %v, wantErr %v", err, tt.wantErr)
return
}
h := hex.EncodeToString(got)
if !reflect.DeepEqual(h, tt.want) {
t.Errorf("GetAddrDescFromVout() = %v, want %v", h, tt.want)
}
})
}
}
func Test_GetAddressesFromAddrDesc(t *testing.T) {
type args struct {
script string
@ -89,6 +159,20 @@ func Test_GetAddressesFromAddrDesc(t *testing.T) {
want2: true,
wantErr: false,
},
{
name: "P2PK compressed",
args: args{script: "21020e46e79a2a8d12b9b5d12c7a91adb4e454edfae43c0a0cb805427d2ac7613fd9ac"},
want: []string{"1P3rU1Nk1pmc2BiWC8dEy9bZa1ZbMp5jfg"},
want2: false,
wantErr: false,
},
{
name: "P2PK uncompressed",
args: args{script: "41041057356b91bfd3efeff5fc0fa8b865faafafb67bd653c5da2cd16ce15c7b86db0e622c8e1e135f68918a23601eb49208c1ac72c7b64a4ee99c396cf788da16ccac"},
want: []string{"1HY6bKYhFH7HF3F48ikvziPHLrEWPGwXcE"},
want2: false,
wantErr: false,
},
{
name: "P2SH",
args: args{script: "a9140394b3cf9a44782c10105b93962daa8dba304d7f87"},