Implement Omni parser for Bitcoin

pull/139/head
Matej Čamaj 2019-03-21 14:31:05 +01:00 committed by Martin
parent 6ac14f163a
commit c0cebd4ce6
3 changed files with 62 additions and 7 deletions

View File

@ -166,7 +166,7 @@ func (p *BCashParser) outputScriptToAddresses(script []byte) ([]string, bool, er
// do not return unknown script type error as error
if err.Error() == "unknown script type" {
// try OP_RETURN script
or := btc.TryParseOPReturn(script)
or := p.TryParseOPReturn(script)
if or != "" {
return []string{or}, false, nil
}

View File

@ -105,7 +105,7 @@ func (p *BitcoinParser) addressToOutputScript(address string) ([]byte, error) {
}
// TryParseOPReturn tries to process OP_RETURN script and return its string representation
func TryParseOPReturn(script []byte) string {
func (p *BitcoinParser) TryParseOPReturn(script []byte) string {
if len(script) > 1 && script[0] == txscript.OP_RETURN {
// trying 2 variants of OP_RETURN data
// 1) OP_RETURN OP_PUSHDATA1 <datalen> <data>
@ -124,8 +124,12 @@ func TryParseOPReturn(script []byte) string {
data = script[2:]
}
if l == len(data) {
var ed string
// TODO try parse OMNI
ed = p.tryOmniParser(data)
if ed != "" {
return ed
}
isASCII := true
for _, c := range data {
@ -134,7 +138,6 @@ func TryParseOPReturn(script []byte) string {
break
}
}
var ed string
if isASCII {
ed = "(" + string(data) + ")"
} else {
@ -146,6 +149,39 @@ func TryParseOPReturn(script []byte) string {
return ""
}
var omniCurrencyMap = map[uint32]string{
1: "Omni",
2: "Test Omni",
31: "TetherUS",
}
// try to parse Omni transaction from script to human-readable string
func (p *BitcoinParser) tryOmniParser(data []byte) string {
// Currently only simple send transaction is supported, see
// https://github.com/OmniLayer/spec#transfer-coins-simple-send
if len(data) != 20 && data[0] != 111 {
return ""
}
// omni (4) <tx_version> (2) <tx_type> (2)
omni_header := []byte{111, 109, 110, 105, 0, 0, 0, 0}
if bytes.Compare(data[0:8], omni_header) != 0 {
return ""
}
currency_id := binary.BigEndian.Uint32(data[8:12])
currency, ok := omniCurrencyMap[currency_id]
if !ok {
return ""
}
amount := new(big.Int)
amount.SetBytes(data[12:])
amount_str := p.AmountToDecimalString(amount)
ed := "OMNI Simple Send " + amount_str + " " + currency + " (#" + strconv.Itoa(int(currency_id)) + ")"
return ed
}
// outputScriptToAddresses converts ScriptPubKey to addresses with a flag that the addresses are searchable
func (p *BitcoinParser) outputScriptToAddresses(script []byte) ([]string, bool, error) {
sc, addresses, _, err := txscript.ExtractPkScriptAddrs(script, p.Params)
@ -160,7 +196,7 @@ func (p *BitcoinParser) outputScriptToAddresses(script []byte) ([]string, bool,
if sc == txscript.PubKeyHashTy || sc == txscript.WitnessV0PubKeyHashTy || sc == txscript.ScriptHashTy || sc == txscript.WitnessV0ScriptHashTy {
s = true
} else if len(rv) == 0 {
or := TryParseOPReturn(script)
or := p.TryParseOPReturn(script)
if or != "" {
rv = []string{or}
}

View File

@ -215,8 +215,27 @@ func TestGetAddressesFromAddrDesc(t *testing.T) {
want2: false,
wantErr: false,
},
// TODO test case for omni
{
name: "OP_RETURN omni simple send tether",
args: args{script: "6a146f6d6e69000000000000001f00000709bb647351"},
want: []string{"OMNI Simple Send 77383.80022609 TetherUS (#31)"},
want2: false,
wantErr: false,
},
{
name: "OP_RETURN omni simple send not supported coin",
args: args{script: "6a146f6d6e69000000000000000300000709bb647351"},
want: []string{"OP_RETURN 6f6d6e69000000000000000300000709bb647351"},
want2: false,
wantErr: false,
},
{
name: "OP_RETURN omni not supported version",
args: args{script: "6a146f6d6e69010000000000000300000709bb647351"},
want: []string{"OP_RETURN 6f6d6e69010000000000000300000709bb647351"},
want2: false,
wantErr: false,
},
}
parser := NewBitcoinParser(GetChainParams("main"), &Configuration{})