diff --git a/blockchain/merkle.go b/blockchain/merkle.go index a1a50a2b..b89b5185 100644 --- a/blockchain/merkle.go +++ b/blockchain/merkle.go @@ -7,6 +7,7 @@ package blockchain import ( "bytes" "fmt" + "io" "math" "github.com/btcsuite/btcd/btcutil" @@ -64,7 +65,10 @@ func HashMerkleBranches(left, right *chainhash.Hash) chainhash.Hash { copy(hash[:chainhash.HashSize], left[:]) copy(hash[chainhash.HashSize:], right[:]) - return chainhash.DoubleHashH(hash[:]) + return chainhash.DoubleHashRaw(func(w io.Writer) error { + _, err := w.Write(hash[:]) + return err + }) } // BuildMerkleTreeStore creates a merkle tree from a slice of transactions, diff --git a/btcutil/psbt/go.mod b/btcutil/psbt/go.mod index b5c4461d..81ccca26 100644 --- a/btcutil/psbt/go.mod +++ b/btcutil/psbt/go.mod @@ -3,9 +3,9 @@ module github.com/btcsuite/btcd/btcutil/psbt go 1.17 require ( - github.com/btcsuite/btcd v0.23.0 + github.com/btcsuite/btcd v0.23.5-0.20231219003633-4c2ce6daed8f github.com/btcsuite/btcd/btcec/v2 v2.1.3 - github.com/btcsuite/btcd/btcutil v1.1.3 + github.com/btcsuite/btcd/btcutil v1.1.4 github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0 github.com/davecgh/go-spew v1.1.1 github.com/stretchr/testify v1.7.0 diff --git a/btcutil/psbt/go.sum b/btcutil/psbt/go.sum index c9d8388f..74a2ce8a 100644 --- a/btcutil/psbt/go.sum +++ b/btcutil/psbt/go.sum @@ -1,15 +1,16 @@ 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= -github.com/btcsuite/btcd v0.23.0 h1:V2/ZgjfDFIygAX3ZapeigkVBoVUtOJKSwrhZdlpSvaA= -github.com/btcsuite/btcd v0.23.0/go.mod h1:0QJIIN1wwIXF/3G/m87gIwGniDMDQqjVn4SZgnFpsYY= +github.com/btcsuite/btcd v0.23.5-0.20231215221805-96c9fd8078fd/go.mod h1:nm3Bko6zh6bWP60UxwoT5LzdGJsQJaPo6HjduXq9p6A= +github.com/btcsuite/btcd v0.23.5-0.20231219003633-4c2ce6daed8f h1:E+dQ8sNtK/lOdfeflUKkRLXe/zW7I333C7HhaoASjZA= +github.com/btcsuite/btcd v0.23.5-0.20231219003633-4c2ce6daed8f/go.mod h1:KVEB81PybLGYzpf1db/kKNi1ZEbUsiVGeTGhKuOl5AM= github.com/btcsuite/btcd/btcec/v2 v2.1.0/go.mod h1:2VzYrv4Gm4apmbVVsSq5bqf1Ec8v56E48Vt0Y/umPgA= github.com/btcsuite/btcd/btcec/v2 v2.1.3 h1:xM/n3yIhHAhHy04z4i43C8p4ehixJZMsnrVJkgl+MTE= github.com/btcsuite/btcd/btcec/v2 v2.1.3/go.mod h1:ctjw4H1kknNJmRN4iP1R7bTQ+v3GJkZBd6mui8ZsAZE= github.com/btcsuite/btcd/btcutil v1.0.0/go.mod h1:Uoxwv0pqYWhD//tfTiipkxNfdhG9UrLwaeswfjfdF0A= github.com/btcsuite/btcd/btcutil v1.1.0/go.mod h1:5OapHB7A2hBBWLm48mmw4MOHNJCcUBTwmWH/0Jn8VHE= -github.com/btcsuite/btcd/btcutil v1.1.3 h1:xfbtw8lwpp0G6NwSHb+UE67ryTFHJAiNuipusjXSohQ= -github.com/btcsuite/btcd/btcutil v1.1.3/go.mod h1:UR7dsSJzJUfMmFiiLlIrMq1lS9jh9EdCV7FStZSnpi0= +github.com/btcsuite/btcd/btcutil v1.1.4 h1:mWvWRLRIPuoeZsVRpc0xNCkfeNxWy1E4jIZ06ZpGI1A= +github.com/btcsuite/btcd/btcutil v1.1.4/go.mod h1:PSZZ4UitpLBWzxGd5VGOrLnmOjtPP/a6HaFo12zMs00= github.com/btcsuite/btcd/chaincfg/chainhash v1.0.0/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0 h1:59Kx4K6lzOW5w6nFlA0v5+lk/6sjybR934QNHSJZPTQ= @@ -46,6 +47,7 @@ github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEW 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/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= 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/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= diff --git a/go.mod b/go.mod index 977682aa..36d4aa21 100644 --- a/go.mod +++ b/go.mod @@ -2,7 +2,7 @@ module github.com/btcsuite/btcd require ( github.com/btcsuite/btcd/btcec/v2 v2.1.3 - github.com/btcsuite/btcd/btcutil v1.1.0 + github.com/btcsuite/btcd/btcutil v1.1.4 github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0 github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd @@ -29,8 +29,6 @@ require ( gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c // indirect ) -replace github.com/btcsuite/btcd/btcutil => ./btcutil - // The retract statements below fixes an accidental push of the tags of a btcd // fork. retract ( diff --git a/go.sum b/go.sum index 9944f70e..6a2ee39c 100644 --- a/go.sum +++ b/go.sum @@ -1,20 +1,33 @@ 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= github.com/btcsuite/btcd v0.23.5-0.20231215221805-96c9fd8078fd/go.mod h1:nm3Bko6zh6bWP60UxwoT5LzdGJsQJaPo6HjduXq9p6A= +github.com/btcsuite/btcd/btcec/v2 v2.1.0/go.mod h1:2VzYrv4Gm4apmbVVsSq5bqf1Ec8v56E48Vt0Y/umPgA= github.com/btcsuite/btcd/btcec/v2 v2.1.3 h1:xM/n3yIhHAhHy04z4i43C8p4ehixJZMsnrVJkgl+MTE= github.com/btcsuite/btcd/btcec/v2 v2.1.3/go.mod h1:ctjw4H1kknNJmRN4iP1R7bTQ+v3GJkZBd6mui8ZsAZE= +github.com/btcsuite/btcd/btcutil v1.0.0/go.mod h1:Uoxwv0pqYWhD//tfTiipkxNfdhG9UrLwaeswfjfdF0A= +github.com/btcsuite/btcd/btcutil v1.1.0/go.mod h1:5OapHB7A2hBBWLm48mmw4MOHNJCcUBTwmWH/0Jn8VHE= +github.com/btcsuite/btcd/btcutil v1.1.4 h1:mWvWRLRIPuoeZsVRpc0xNCkfeNxWy1E4jIZ06ZpGI1A= +github.com/btcsuite/btcd/btcutil v1.1.4/go.mod h1:PSZZ4UitpLBWzxGd5VGOrLnmOjtPP/a6HaFo12zMs00= github.com/btcsuite/btcd/chaincfg/chainhash v1.0.0/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0 h1:59Kx4K6lzOW5w6nFlA0v5+lk/6sjybR934QNHSJZPTQ= github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f h1:bAs4lUbRJpnnkd9VhRV3jjAVU7DJVjMaK+IsvSeZvFo= github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA= +github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd h1:R/opQEbFEy9JGkIguV40SvRY1uliPX8ifOvi6ICsFCw= github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd/go.mod h1:HHNXQzUsZCxOoE+CPiyCTO6x34Zs86zZUiwtpXoGdtg= +github.com/btcsuite/goleveldb v0.0.0-20160330041536-7834afc9e8cd/go.mod h1:F+uVaaLLH7j4eDXPRvw78tMflu7Ie2bzYOH4Y8rRKBY= +github.com/btcsuite/goleveldb v1.0.0/go.mod h1:QiK9vBlgftBg6rWQIj6wFzbPfRjiykIEhBH4obrXJ/I= +github.com/btcsuite/snappy-go v0.0.0-20151229074030-0bdef8d06723/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc= +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= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -42,6 +55,7 @@ github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= 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= @@ -51,9 +65,12 @@ github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6 github.com/nxadm/tail v1.4.4 h1:DQuhQpB1tVlglWS2hLQ5OV6B5r8aGxSrPc5Qo6uTN78= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= github.com/onsi/ginkgo v1.14.0 h1:2mOpI4JVVPBN+WQRa0WKH2eXR+Ey+uK4n7Zj0aYpIQA= github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= +github.com/onsi/gomega v1.4.1/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= +github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= github.com/onsi/gomega v1.10.1 h1:o0+MgICZLuZ7xjH7Vx6zS/zcu93/BEp1VwkIW1mEXCE= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= @@ -64,9 +81,11 @@ github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5Cc 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= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= @@ -102,6 +121,7 @@ gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8 gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= +gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU= gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= diff --git a/txscript/sighash.go b/txscript/sighash.go index 7dc19ab5..16c3c19c 100644 --- a/txscript/sighash.go +++ b/txscript/sighash.go @@ -169,10 +169,18 @@ func calcSignatureHash(sigScript []byte, hashType SigHashType, tx *wire.MsgTx, i // The final hash is the double sha256 of both the serialized modified // transaction and the hash type (encoded as a 4-byte little-endian // value) appended. - wbuf := bytes.NewBuffer(make([]byte, 0, txCopy.SerializeSizeStripped()+4)) - txCopy.SerializeNoWitness(wbuf) - binary.Write(wbuf, binary.LittleEndian, hashType) - return chainhash.DoubleHashB(wbuf.Bytes()) + sigHashBytes := chainhash.DoubleHashRaw(func(w io.Writer) error { + if err := txCopy.SerializeNoWitness(w); err != nil { + return err + } + err := binary.Write(w, binary.LittleEndian, hashType) + if err != nil { + return err + } + return nil + }) + + return sigHashBytes[:] } // calcWitnessSignatureHashRaw computes the sighash digest of a transaction's @@ -197,99 +205,107 @@ func calcWitnessSignatureHashRaw(subScript []byte, sigHashes *TxSigHashes, return nil, fmt.Errorf("idx %d but %d txins", idx, len(tx.TxIn)) } - // We'll utilize this buffer throughout to incrementally calculate - // the signature hash for this transaction. - var sigHash bytes.Buffer + sigHashBytes := chainhash.DoubleHashRaw(func(w io.Writer) error { + var scratch [8]byte - // First write out, then encode the transaction's version number. - var bVersion [4]byte - binary.LittleEndian.PutUint32(bVersion[:], uint32(tx.Version)) - sigHash.Write(bVersion[:]) + // First write out, then encode the transaction's version + // number. + binary.LittleEndian.PutUint32(scratch[:], uint32(tx.Version)) + w.Write(scratch[:4]) - // Next write out the possibly pre-calculated hashes for the sequence - // numbers of all inputs, and the hashes of the previous outs for all - // outputs. - var zeroHash chainhash.Hash + // Next write out the possibly pre-calculated hashes for the + // sequence numbers of all inputs, and the hashes of the + // previous outs for all outputs. + var zeroHash chainhash.Hash - // If anyone can pay isn't active, then we can use the cached - // hashPrevOuts, otherwise we just write zeroes for the prev outs. - if hashType&SigHashAnyOneCanPay == 0 { - sigHash.Write(sigHashes.HashPrevOutsV0[:]) - } else { - sigHash.Write(zeroHash[:]) - } + // If anyone can pay isn't active, then we can use the cached + // hashPrevOuts, otherwise we just write zeroes for the prev + // outs. + if hashType&SigHashAnyOneCanPay == 0 { + w.Write(sigHashes.HashPrevOutsV0[:]) + } else { + w.Write(zeroHash[:]) + } - // If the sighash isn't anyone can pay, single, or none, the use the - // cached hash sequences, otherwise write all zeroes for the - // hashSequence. - if hashType&SigHashAnyOneCanPay == 0 && - hashType&sigHashMask != SigHashSingle && - hashType&sigHashMask != SigHashNone { - sigHash.Write(sigHashes.HashSequenceV0[:]) - } else { - sigHash.Write(zeroHash[:]) - } + // If the sighash isn't anyone can pay, single, or none, the + // use the cached hash sequences, otherwise write all zeroes + // for the hashSequence. + if hashType&SigHashAnyOneCanPay == 0 && + hashType&sigHashMask != SigHashSingle && + hashType&sigHashMask != SigHashNone { - txIn := tx.TxIn[idx] + w.Write(sigHashes.HashSequenceV0[:]) + } else { + w.Write(zeroHash[:]) + } - // Next, write the outpoint being spent. - sigHash.Write(txIn.PreviousOutPoint.Hash[:]) - var bIndex [4]byte - binary.LittleEndian.PutUint32(bIndex[:], txIn.PreviousOutPoint.Index) - sigHash.Write(bIndex[:]) + txIn := tx.TxIn[idx] - if isWitnessPubKeyHashScript(subScript) { - // The script code for a p2wkh is a length prefix varint for - // the next 25 bytes, followed by a re-creation of the original - // p2pkh pk script. - sigHash.Write([]byte{0x19}) - sigHash.Write([]byte{OP_DUP}) - sigHash.Write([]byte{OP_HASH160}) - sigHash.Write([]byte{OP_DATA_20}) - sigHash.Write(extractWitnessPubKeyHash(subScript)) - sigHash.Write([]byte{OP_EQUALVERIFY}) - sigHash.Write([]byte{OP_CHECKSIG}) - } else { - // For p2wsh outputs, and future outputs, the script code is - // the original script, with all code separators removed, - // serialized with a var int length prefix. - wire.WriteVarBytes(&sigHash, 0, subScript) - } + // Next, write the outpoint being spent. + w.Write(txIn.PreviousOutPoint.Hash[:]) + var bIndex [4]byte + binary.LittleEndian.PutUint32( + bIndex[:], txIn.PreviousOutPoint.Index, + ) + w.Write(bIndex[:]) - // Next, add the input amount, and sequence number of the input being - // signed. - var bAmount [8]byte - binary.LittleEndian.PutUint64(bAmount[:], uint64(amt)) - sigHash.Write(bAmount[:]) - var bSequence [4]byte - binary.LittleEndian.PutUint32(bSequence[:], txIn.Sequence) - sigHash.Write(bSequence[:]) + if isWitnessPubKeyHashScript(subScript) { + // The script code for a p2wkh is a length prefix + // varint for the next 25 bytes, followed by a + // re-creation of the original p2pkh pk script. + w.Write([]byte{0x19}) + w.Write([]byte{OP_DUP}) + w.Write([]byte{OP_HASH160}) + w.Write([]byte{OP_DATA_20}) + w.Write(extractWitnessPubKeyHash(subScript)) + w.Write([]byte{OP_EQUALVERIFY}) + w.Write([]byte{OP_CHECKSIG}) + } else { + // For p2wsh outputs, and future outputs, the script + // code is the original script, with all code + // separators removed, serialized with a var int length + // prefix. + wire.WriteVarBytes(w, 0, subScript) + } - // If the current signature mode isn't single, or none, then we can - // re-use the pre-generated hashoutputs sighash fragment. Otherwise, - // we'll serialize and add only the target output index to the signature - // pre-image. - if hashType&sigHashMask != SigHashSingle && - hashType&sigHashMask != SigHashNone { - sigHash.Write(sigHashes.HashOutputsV0[:]) - } else if hashType&sigHashMask == SigHashSingle && idx < len(tx.TxOut) { - var b bytes.Buffer - wire.WriteTxOut(&b, 0, 0, tx.TxOut[idx]) - sigHash.Write(chainhash.DoubleHashB(b.Bytes())) - } else { - sigHash.Write(zeroHash[:]) - } + // Next, add the input amount, and sequence number of the input + // being signed. + binary.LittleEndian.PutUint64(scratch[:], uint64(amt)) + w.Write(scratch[:]) + binary.LittleEndian.PutUint32(scratch[:], txIn.Sequence) + w.Write(scratch[:4]) - // Finally, write out the transaction's locktime, and the sig hash - // type. - var bLockTime [4]byte - binary.LittleEndian.PutUint32(bLockTime[:], tx.LockTime) - sigHash.Write(bLockTime[:]) - var bHashType [4]byte - binary.LittleEndian.PutUint32(bHashType[:], uint32(hashType)) - sigHash.Write(bHashType[:]) + // If the current signature mode isn't single, or none, then we + // can re-use the pre-generated hashoutputs sighash fragment. + // Otherwise, we'll serialize and add only the target output + // index to the signature pre-image. + if hashType&sigHashMask != SigHashSingle && + hashType&sigHashMask != SigHashNone { - return chainhash.DoubleHashB(sigHash.Bytes()), nil + w.Write(sigHashes.HashOutputsV0[:]) + } else if hashType&sigHashMask == SigHashSingle && + idx < len(tx.TxOut) { + + h := chainhash.DoubleHashRaw(func(tw io.Writer) error { + wire.WriteTxOut(tw, 0, 0, tx.TxOut[idx]) + return nil + }) + w.Write(h[:]) + } else { + w.Write(zeroHash[:]) + } + + // Finally, write out the transaction's locktime, and the sig + // hash type. + binary.LittleEndian.PutUint32(scratch[:], tx.LockTime) + w.Write(scratch[:4]) + binary.LittleEndian.PutUint32(scratch[:], uint32(hashType)) + w.Write(scratch[:4]) + + return nil + }) + + return sigHashBytes[:], nil } // CalcWitnessSigHash computes the sighash digest for the specified input of diff --git a/wire/blockheader.go b/wire/blockheader.go index 9c9c2237..7af9a378 100644 --- a/wire/blockheader.go +++ b/wire/blockheader.go @@ -5,7 +5,6 @@ package wire import ( - "bytes" "io" "time" @@ -46,14 +45,9 @@ const blockHeaderLen = 80 // BlockHash computes the block identifier hash for the given block header. func (h *BlockHeader) BlockHash() chainhash.Hash { - // Encode the header and double sha256 everything prior to the number of - // transactions. Ignore the error returns since there is no way the - // encode could fail except being out of memory which would cause a - // run-time panic. - buf := bytes.NewBuffer(make([]byte, 0, MaxBlockHeaderPayload)) - _ = writeBlockHeader(buf, 0, h) - - return chainhash.DoubleHashH(buf.Bytes()) + return chainhash.DoubleHashRaw(func(w io.Writer) error { + return writeBlockHeader(w, 0, h) + }) } // BtcDecode decodes r using the bitcoin protocol encoding into the receiver. diff --git a/wire/msgtx.go b/wire/msgtx.go index 7705504c..d2b52dba 100644 --- a/wire/msgtx.go +++ b/wire/msgtx.go @@ -5,7 +5,6 @@ package wire import ( - "bytes" "errors" "fmt" "io" @@ -357,13 +356,7 @@ func (msg *MsgTx) AddTxOut(to *TxOut) { // TxHash generates the Hash for the transaction. func (msg *MsgTx) TxHash() chainhash.Hash { - // Encode the transaction and calculate double sha256 on the result. - // Ignore the error returns since the only way the encode could fail - // is being out of memory or due to nil pointers, both of which would - // cause a run-time panic. - buf := bytes.NewBuffer(make([]byte, 0, msg.SerializeSizeStripped())) - _ = msg.SerializeNoWitness(buf) - return chainhash.DoubleHashH(buf.Bytes()) + return chainhash.DoubleHashRaw(msg.SerializeNoWitness) } // WitnessHash generates the hash of the transaction serialized according to @@ -373,9 +366,7 @@ func (msg *MsgTx) TxHash() chainhash.Hash { // is the same as its txid. func (msg *MsgTx) WitnessHash() chainhash.Hash { if msg.HasWitness() { - buf := bytes.NewBuffer(make([]byte, 0, msg.SerializeSize())) - _ = msg.Serialize(buf) - return chainhash.DoubleHashH(buf.Bytes()) + return chainhash.DoubleHashRaw(msg.Serialize) } return msg.TxHash()