From 70fbb90c78961b29364b9f33ec04ca7b89ec8b21 Mon Sep 17 00:00:00 2001 From: Javed Khan Date: Fri, 3 Mar 2023 18:50:05 -0800 Subject: [PATCH] read: fix script matching --- go.mod | 10 ++++++ go.sum | 10 ++++++ relayer.go | 91 ++++++++++++++++++++++++++++++++++++------------------ 3 files changed, 81 insertions(+), 30 deletions(-) diff --git a/go.mod b/go.mod index b987fff..81c5c46 100644 --- a/go.mod +++ b/go.mod @@ -10,11 +10,21 @@ require ( ) require ( + github.com/aead/siphash v1.0.1 // indirect github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f // indirect github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd // indirect github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792 // indirect + github.com/btcsuite/winsvc v1.0.0 // indirect + github.com/davecgh/go-spew v1.1.1 // indirect github.com/decred/dcrd/crypto/blake256 v1.0.0 // indirect github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 // indirect + github.com/decred/dcrd/lru v1.0.0 // indirect + github.com/golang/snappy v0.0.4 // indirect + github.com/jessevdk/go-flags v1.4.0 // indirect + github.com/jrick/logrotate v1.0.0 // indirect + github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23 // indirect + github.com/rollkit/btcd v0.0.0-20230304003258-065fdfb84b46 // indirect + github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 // indirect golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 // indirect golang.org/x/sys v0.0.0-20200814200057-3d37ad5750ed // indirect ) diff --git a/go.sum b/go.sum index c54f555..ff60f22 100644 --- a/go.sum +++ b/go.sum @@ -1,3 +1,4 @@ +github.com/aead/siphash v1.0.1 h1:FwHfE/T45KPKYuuSAKyyvE+oPWcaQ+CUmFW0bPlM+kg= github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= github.com/btcsuite/btcd v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ= github.com/btcsuite/btcd v0.22.0-beta.0.20220111032746-97732e52810c/go.mod h1:tjmYdS6MLJ5/s0Fj4DbLgSbDHbEqLJrtnHecBFkdz5M= @@ -25,6 +26,7 @@ github.com/btcsuite/snappy-go v0.0.0-20151229074030-0bdef8d06723/go.mod h1:8woku github.com/btcsuite/snappy-go v1.0.0/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc= github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792 h1:R8vQdOQdZ9Y3SkEwmHoWBmX1DNXhXZqlTpq6s4tyJGc= github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtEyQwv5/p4Mg4C0fgbePVuGr935/5ddU9Z3TmDRY= +github.com/btcsuite/winsvc v1.0.0 h1:J9B4L7e3oqhXOcm+2IuNApwzQec85lE+QaikUcCs+dk= github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs= github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -34,6 +36,7 @@ github.com/decred/dcrd/crypto/blake256 v1.0.0 h1:/8DMNYp9SGi5f0w7uCm6d6M4OU2rGFK github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 h1:YLtO71vCjJRCBcrPMtQ9nqBsqpA1m5sE92cU+pd5Mcc= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1/go.mod h1:hyedUtir6IdtD/7lIxGeCxkaw7y45JueMRL4DIyJDKs= +github.com/decred/dcrd/lru v1.0.0 h1:Kbsb1SFDsIlaupWPwsPp+dkxiBY1frcS07PCPgotKz8= github.com/decred/dcrd/lru v1.0.0/go.mod h1:mxKOwFd7lFjN2GZYsiz/ecgqR6kkYAl+0pz0tEMk218= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= @@ -44,14 +47,18 @@ github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrU github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= +github.com/jessevdk/go-flags v1.4.0 h1:4IU2WS7AumrZ/40jfhf4QVDMsQwqA7VEHozFRrGARJA= github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= +github.com/jrick/logrotate v1.0.0 h1:lQ1bL/n9mBNeIXoTUoYRlK4dHuNJVofX9oWqBtPnSzI= github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ= +github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23 h1:FOOIBWrEkLgmlgGfMuZT83xIwfPDxEI2OHu6xUmJMFE= github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= @@ -64,9 +71,12 @@ github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7J github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/rollkit/btcd v0.0.0-20230304003258-065fdfb84b46 h1:Svr3WAt5xHdE+JgoS5r7Z+aSMhxtNvnHPItWsrlEXAY= +github.com/rollkit/btcd v0.0.0-20230304003258-065fdfb84b46/go.mod h1:FewIyVo3jCTveMYfXOJDGhUNTA6MbxH6pBJdaW/cDro= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 h1:epCh84lMvA70Z7CTTCmYQn2CKbY8j86K7/FAIr141uY= github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7/go.mod h1:q4W45IWZaF22tdD+VEXcAWRA037jwmWEB5VWYORlTpc= golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= diff --git a/relayer.go b/relayer.go index 5e8f45b..4566b11 100644 --- a/relayer.go +++ b/relayer.go @@ -287,22 +287,14 @@ func (r Relayer) ReadTransaction(hash *chainhash.Hash) ([]byte, error) { return nil, err } if len(tx.MsgTx().TxIn[0].Witness) > 1 { - // FIXME: UGLY HACK - // ideally we should template match the script and extract - // see: txscript.ExtractAtomicSwapDataPushes witness := tx.MsgTx().TxIn[0].Witness[1] - start := bytes.Index(witness, PROTOCOL_ID) - // script template: - // < --------- 35 bytes ---------> - // OP_FALSE OP_IF + "roll" marker + + canonical int + 32 bytes pubkey + OP_CHECKSIG - // ^ ^ - // start ------------ ^ - // end ------------------------------------- - if start > 0 && len(witness) > start+35 { - end := len(witness) - 35 - if end > start { - return witness[start+4 : end], nil - } + pushData, err := ExtractPushData(0, witness) + if err != nil { + return nil, err + } + // skip PROTOCOL_ID + if pushData != nil && bytes.HasPrefix(pushData, PROTOCOL_ID) { + return pushData[4:], nil } } return nil, nil @@ -321,22 +313,14 @@ func (r Relayer) Read(height uint64) ([][]byte, error) { var data [][]byte for _, tx := range block.Transactions { if len(tx.TxIn[0].Witness) > 1 { - // FIXME: UGLY HACK - // ideally we should template match the script and extract - // see: txscript.ExtractAtomicSwapDataPushes witness := tx.TxIn[0].Witness[1] - start := bytes.Index(witness, PROTOCOL_ID) - // script template: - // < --------- 35 bytes ---------> - // OP_FALSE OP_IF + "roll" marker + + canonical int + 32 bytes pubkey + OP_CHECKSIG - // ^ ^ - // start ------------ ^ - // end ------------------------------------- - if start > 0 && len(witness) > start+35 { - end := len(witness) - 35 - if end > start { - data = append(data, witness[start+4:end]) - } + pushData, err := ExtractPushData(0, witness) + if err != nil { + return nil, err + } + // skip PROTOCOL_ID + if pushData != nil && bytes.HasPrefix(pushData, PROTOCOL_ID) { + data = append(data, pushData[4:]) } } } @@ -359,3 +343,50 @@ func (r Relayer) Write(data []byte) (*chainhash.Hash, error) { } return hash, nil } + +func ExtractPushData(version uint16, pkScript []byte) ([]byte, error) { + type templateMatch struct { + expectPushData bool + maxPushDatas int + opcode byte + extractedData []byte + } + var template = [6]templateMatch{ + {opcode: txscript.OP_FALSE}, + {opcode: txscript.OP_IF}, + {expectPushData: true, maxPushDatas: 10}, + {opcode: txscript.OP_ENDIF}, + {expectPushData: true, maxPushDatas: 1}, + {opcode: txscript.OP_CHECKSIG}, + } + + var templateOffset int + tokenizer := txscript.MakeScriptTokenizer(version, pkScript) +out: + for tokenizer.Next() { + // Not a rollkit script if it has more opcodes than expected in the + // template. + if templateOffset >= len(template) { + return nil, nil + } + + op := tokenizer.Opcode() + tplEntry := &template[templateOffset] + if tplEntry.expectPushData { + for i := 0; i < tplEntry.maxPushDatas; i++ { + data := tokenizer.Data() + if data == nil { + break out + } + tplEntry.extractedData = append(tplEntry.extractedData, data...) + tokenizer.Next() + } + } else if op != tplEntry.opcode { + return nil, nil + } + + templateOffset++ + } + // TODO: skipping err checks + return template[2].extractedData, nil +}