Process OP_RETURN script in Bcash
This commit is contained in:
parent
fe4b366875
commit
1b69a62ab8
@ -223,7 +223,7 @@ func (w *Worker) txFromTxAddress(txid string, ta *db.TxAddresses, bi *db.BlockIn
|
|||||||
valInSat.Add(&valInSat, &vin.ValueSat)
|
valInSat.Add(&valInSat, &vin.ValueSat)
|
||||||
vin.Addresses, vin.Searchable, err = tai.Addresses(w.chainParser)
|
vin.Addresses, vin.Searchable, err = tai.Addresses(w.chainParser)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
glog.Errorf("tai.Addresses error %v, tx %v, input %v", err, txid, i)
|
glog.Errorf("tai.Addresses error %v, tx %v, input %v, tai %+v", err, txid, i, tai)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
vouts := make([]Vout, len(ta.Outputs))
|
vouts := make([]Vout, len(ta.Outputs))
|
||||||
@ -236,7 +236,7 @@ func (w *Worker) txFromTxAddress(txid string, ta *db.TxAddresses, bi *db.BlockIn
|
|||||||
valOutSat.Add(&valOutSat, &vout.ValueSat)
|
valOutSat.Add(&valOutSat, &vout.ValueSat)
|
||||||
vout.ScriptPubKey.Addresses, vout.ScriptPubKey.Searchable, err = tao.Addresses(w.chainParser)
|
vout.ScriptPubKey.Addresses, vout.ScriptPubKey.Searchable, err = tao.Addresses(w.chainParser)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
glog.Errorf("tai.Addresses error %v, tx %v, output %v", err, txid, i)
|
glog.Errorf("tai.Addresses error %v, tx %v, output %v, tao %+v", err, txid, i, tao)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// for coinbase transactions valIn is 0
|
// for coinbase transactions valIn is 0
|
||||||
|
|||||||
@ -126,6 +126,15 @@ func isCashAddr(addr string) bool {
|
|||||||
func (p *BCashParser) outputScriptToAddresses(script []byte) ([]string, bool, error) {
|
func (p *BCashParser) outputScriptToAddresses(script []byte) ([]string, bool, error) {
|
||||||
a, err := bchutil.ExtractPkScriptAddrs(script, p.Params)
|
a, err := bchutil.ExtractPkScriptAddrs(script, p.Params)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
// do not return unknown script type error as error
|
||||||
|
if err.Error() == "unknown script type" {
|
||||||
|
// try OP_RETURN script
|
||||||
|
or := btc.TryParseOPReturn(script)
|
||||||
|
if or != "" {
|
||||||
|
return []string{or}, false, nil
|
||||||
|
}
|
||||||
|
return []string{}, false, nil
|
||||||
|
}
|
||||||
return nil, false, err
|
return nil, false, err
|
||||||
}
|
}
|
||||||
// EncodeAddress returns CashAddr address
|
// EncodeAddress returns CashAddr address
|
||||||
|
|||||||
@ -82,53 +82,85 @@ func Test_GetAddrDescFromAddress(t *testing.T) {
|
|||||||
func Test_GetAddressesFromAddrDesc(t *testing.T) {
|
func Test_GetAddressesFromAddrDesc(t *testing.T) {
|
||||||
mainParserCashAddr, mainParserLegacy, testParserCashAddr, testParserLegacy := setupParsers(t)
|
mainParserCashAddr, mainParserLegacy, testParserCashAddr, testParserLegacy := setupParsers(t)
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
parser *BCashParser
|
parser *BCashParser
|
||||||
addresses []string
|
addresses []string
|
||||||
hex string
|
searchable bool
|
||||||
wantErr bool
|
hex string
|
||||||
|
wantErr bool
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "test-P2PKH-0",
|
name: "test-P2PKH-0",
|
||||||
parser: testParserLegacy,
|
parser: testParserLegacy,
|
||||||
addresses: []string{"mnnAKPTSrWjgoi3uEYaQkHA1QEC5btFeBr"},
|
addresses: []string{"mnnAKPTSrWjgoi3uEYaQkHA1QEC5btFeBr"},
|
||||||
hex: "76a9144fa927fd3bcf57d4e3c582c3d2eb2bd3df8df47c88ac",
|
searchable: true,
|
||||||
wantErr: false,
|
hex: "76a9144fa927fd3bcf57d4e3c582c3d2eb2bd3df8df47c88ac",
|
||||||
|
|
||||||
|
wantErr: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "test-P2PKH-1",
|
name: "test-P2PKH-1",
|
||||||
parser: testParserCashAddr,
|
parser: testParserCashAddr,
|
||||||
addresses: []string{"bchtest:qp86jfla8084048rckpv85ht90falr050s03ejaesm"},
|
addresses: []string{"bchtest:qp86jfla8084048rckpv85ht90falr050s03ejaesm"},
|
||||||
hex: "76a9144fa927fd3bcf57d4e3c582c3d2eb2bd3df8df47c88ac",
|
searchable: true,
|
||||||
wantErr: false,
|
hex: "76a9144fa927fd3bcf57d4e3c582c3d2eb2bd3df8df47c88ac",
|
||||||
|
wantErr: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "main-P2PKH-0",
|
name: "main-P2PKH-0",
|
||||||
parser: mainParserLegacy,
|
parser: mainParserLegacy,
|
||||||
addresses: []string{"129HiRqekqPVucKy2M8zsqvafGgKypciPp"},
|
addresses: []string{"129HiRqekqPVucKy2M8zsqvafGgKypciPp"},
|
||||||
hex: "76a9140c8967e6382c7a2ca64d8e850bfc99b7736e1a0d88ac",
|
searchable: true,
|
||||||
wantErr: false,
|
hex: "76a9140c8967e6382c7a2ca64d8e850bfc99b7736e1a0d88ac",
|
||||||
|
wantErr: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "main-P2PKH-0",
|
name: "main-P2PKH-0",
|
||||||
parser: mainParserCashAddr,
|
parser: mainParserCashAddr,
|
||||||
addresses: []string{"bitcoincash:qqxgjelx8qk85t9xfk8g2zlunxmhxms6p55xarv2r5"},
|
addresses: []string{"bitcoincash:qqxgjelx8qk85t9xfk8g2zlunxmhxms6p55xarv2r5"},
|
||||||
hex: "76a9140c8967e6382c7a2ca64d8e850bfc99b7736e1a0d88ac",
|
searchable: true,
|
||||||
wantErr: false,
|
hex: "76a9140c8967e6382c7a2ca64d8e850bfc99b7736e1a0d88ac",
|
||||||
|
wantErr: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "main-P2SH-0",
|
name: "main-P2SH-0",
|
||||||
parser: mainParserLegacy,
|
parser: mainParserLegacy,
|
||||||
addresses: []string{"3EBEFWPtDYWCNszQ7etoqtWmmygccayLiH"},
|
addresses: []string{"3EBEFWPtDYWCNszQ7etoqtWmmygccayLiH"},
|
||||||
hex: "a91488f772450c830a30eddfdc08a93d5f2ae1a30e1787",
|
searchable: true,
|
||||||
wantErr: false,
|
hex: "a91488f772450c830a30eddfdc08a93d5f2ae1a30e1787",
|
||||||
|
wantErr: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "main-P2SH-1",
|
name: "main-P2SH-1",
|
||||||
parser: mainParserCashAddr,
|
parser: mainParserCashAddr,
|
||||||
addresses: []string{"bitcoincash:pzy0wuj9pjps5v8dmlwq32fatu4wrgcwzuayq5nfhh"},
|
addresses: []string{"bitcoincash:pzy0wuj9pjps5v8dmlwq32fatu4wrgcwzuayq5nfhh"},
|
||||||
hex: "a91488f772450c830a30eddfdc08a93d5f2ae1a30e1787",
|
searchable: true,
|
||||||
wantErr: false,
|
hex: "a91488f772450c830a30eddfdc08a93d5f2ae1a30e1787",
|
||||||
|
wantErr: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "OP_RETURN ascii",
|
||||||
|
parser: mainParserCashAddr,
|
||||||
|
addresses: []string{"OP_RETURN (ahoj)"},
|
||||||
|
searchable: false,
|
||||||
|
hex: "6a0461686f6a",
|
||||||
|
wantErr: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "OP_RETURN hex",
|
||||||
|
parser: mainParserCashAddr,
|
||||||
|
addresses: []string{"OP_RETURN 07 2020f1686f6a20"},
|
||||||
|
searchable: false,
|
||||||
|
hex: "6a072020f1686f6a20",
|
||||||
|
wantErr: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "empty",
|
||||||
|
parser: mainParserCashAddr,
|
||||||
|
addresses: []string{},
|
||||||
|
searchable: false,
|
||||||
|
hex: "",
|
||||||
|
wantErr: false,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -143,8 +175,8 @@ func Test_GetAddressesFromAddrDesc(t *testing.T) {
|
|||||||
if !reflect.DeepEqual(got, tt.addresses) {
|
if !reflect.DeepEqual(got, tt.addresses) {
|
||||||
t.Errorf("GetAddressesFromAddrDesc() = %v, want %v", got, tt.addresses)
|
t.Errorf("GetAddressesFromAddrDesc() = %v, want %v", got, tt.addresses)
|
||||||
}
|
}
|
||||||
if !reflect.DeepEqual(got2, true) {
|
if !reflect.DeepEqual(got2, tt.searchable) {
|
||||||
t.Errorf("GetAddressesFromAddrDesc() = %v, want %v", got2, true)
|
t.Errorf("GetAddressesFromAddrDesc() = %v, want %v", got2, tt.searchable)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@ -84,6 +84,31 @@ func (p *BitcoinParser) addressToOutputScript(address string) ([]byte, error) {
|
|||||||
return script, nil
|
return script, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TryParseOPReturn tries to process OP_RETURN script and return its string representation
|
||||||
|
func TryParseOPReturn(script []byte) string {
|
||||||
|
if len(script) > 1 && script[0] == txscript.OP_RETURN {
|
||||||
|
l := int(script[1])
|
||||||
|
data := script[2:]
|
||||||
|
if l == len(data) {
|
||||||
|
isASCII := true
|
||||||
|
for _, c := range data {
|
||||||
|
if c < 32 || c > 127 {
|
||||||
|
isASCII = false
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var ed string
|
||||||
|
if isASCII {
|
||||||
|
ed = "(" + string(data) + ")"
|
||||||
|
} else {
|
||||||
|
ed = hex.EncodeToString([]byte{byte(l)}) + " " + hex.EncodeToString(data)
|
||||||
|
}
|
||||||
|
return "OP_RETURN " + ed
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
// outputScriptToAddresses converts ScriptPubKey to bitcoin addresses
|
// outputScriptToAddresses converts ScriptPubKey to bitcoin addresses
|
||||||
func (p *BitcoinParser) outputScriptToAddresses(script []byte) ([]string, bool, error) {
|
func (p *BitcoinParser) outputScriptToAddresses(script []byte) ([]string, bool, error) {
|
||||||
sc, addresses, _, err := txscript.ExtractPkScriptAddrs(script, p.Params)
|
sc, addresses, _, err := txscript.ExtractPkScriptAddrs(script, p.Params)
|
||||||
@ -97,26 +122,10 @@ func (p *BitcoinParser) outputScriptToAddresses(script []byte) ([]string, bool,
|
|||||||
var s bool
|
var s bool
|
||||||
if sc != txscript.NonStandardTy && sc != txscript.NullDataTy {
|
if sc != txscript.NonStandardTy && sc != txscript.NullDataTy {
|
||||||
s = true
|
s = true
|
||||||
} else {
|
} else if len(rv) == 0 {
|
||||||
if len(script) > 1 && script[0] == txscript.OP_RETURN && len(rv) == 0 {
|
or := TryParseOPReturn(script)
|
||||||
l := int(script[1])
|
if or != "" {
|
||||||
data := script[2:]
|
rv = []string{or}
|
||||||
if l == len(data) {
|
|
||||||
isASCII := true
|
|
||||||
for _, c := range data {
|
|
||||||
if c < 32 || c > 127 {
|
|
||||||
isASCII = false
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
var ed string
|
|
||||||
if isASCII {
|
|
||||||
ed = "(" + string(data) + ")"
|
|
||||||
} else {
|
|
||||||
ed = hex.EncodeToString([]byte{byte(l)}) + " " + hex.EncodeToString(data)
|
|
||||||
}
|
|
||||||
rv = []string{"OP_RETURN " + ed}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return rv, s, nil
|
return rv, s, nil
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user