diff --git a/.golangci.yml b/.golangci.yml index 2a40d0f..c31ef8e 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -21,43 +21,40 @@ linters-settings: - opinionated - performance - style - disabled-checks: - - dupImport # https://github.com/go-critic/go-critic/issues/845 - - ifElseChain - - octalLiteral - - whyNoLint - - wrapperFunc goimports: local-prefixes: github.com/bitonicnl/verify-signed-message - govet: - check-shadowing: true - settings: - printf: - funcs: - - (github.com/golangci/golangci-lint/pkg/logutils.Log).Infof - - (github.com/golangci/golangci-lint/pkg/logutils.Log).Warnf - - (github.com/golangci/golangci-lint/pkg/logutils.Log).Errorf - - (github.com/golangci/golangci-lint/pkg/logutils.Log).Fatalf misspell: locale: US linters: enable: - asasalint + - asciicheck - bidichk - bodyclose + - containedctx + - contextcheck - decorder - dogsled - dupl + - dupword + - durationcheck - errcheck - errchkjson + - errname - errorlint + - execinquery - exhaustive - exhaustruct - exportloopref - forbidigo + - forcetypeassert - gci + - ginkgolinter + - gocheckcompilerdirectives + - gochecknoglobals - gochecknoinits + - gochecksumtype - gocognit - goconst - gocritic @@ -73,39 +70,59 @@ linters: - goprintffuncname - gosec - gosimple + - gosmopolitan - govet - grouper + - importas + - inamedparam - ineffassign - interfacebloat - ireturn - loggercheck - maintidx - makezero + - mirror - misspell + - musttag - nakedret - nestif + - nilerr - nilnil - nlreturn + - noctx - nolintlint - nonamedreturns + - nosprintfhostport - paralleltest + - perfsprint - prealloc - predeclared - promlinter + - protogetter - reassign - revive + - rowserrcheck + - sloglint + - spancheck + - sqlclosecheck - staticcheck - stylecheck + - tagalign - tagliatelle - tenv + - testableexamples + - testifylint - testpackage - thelper + - tparallel - typecheck - unconvert - unparam - unused - usestdlibvars + - wastedassign - whitespace + - zerologlint issues: # Show only new issues: if there are unstaged changes or untracked files, @@ -117,12 +134,13 @@ issues: # Exclude some linters from running on tests files - path: _test\.go linters: + - dupword - exhaustruct # output configuration options output: # colored-line-number|line-number|json|tab|checkstyle|code-climate, default is "colored-line-number" - format: colored-line-number + formats: [ { format: colored-line-number } ] # print lines of code with issue, default is true print-issued-lines: true diff --git a/go.mod b/go.mod index f9007dc..ddbfbab 100644 --- a/go.mod +++ b/go.mod @@ -4,21 +4,21 @@ go 1.18 require ( github.com/btcsuite/btcd v0.24.0 - github.com/btcsuite/btcd/btcec/v2 v2.3.2 + github.com/btcsuite/btcd/btcec/v2 v2.3.3 github.com/btcsuite/btcd/btcutil v1.1.5 github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0 - github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 + github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 github.com/samber/lo v1.39.0 - github.com/stretchr/testify v1.8.4 + github.com/stretchr/testify v1.9.0 ) require ( github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f // indirect - github.com/davecgh/go-spew v1.1.1 // indirect + github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/decred/dcrd/crypto/blake256 v1.0.1 // indirect - github.com/pmezard/go-difflib v1.0.0 // indirect - golang.org/x/crypto v0.20.0 // indirect - golang.org/x/exp v0.0.0-20240222234643-814bf88cf225 // indirect - golang.org/x/sys v0.17.0 // indirect + github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect + golang.org/x/crypto v0.22.0 // indirect + golang.org/x/exp v0.0.0-20240416160154-fe59bbe5cc7f // indirect + golang.org/x/sys v0.19.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index ca766e7..cd0b3b8 100644 --- a/go.sum +++ b/go.sum @@ -6,8 +6,8 @@ github.com/btcsuite/btcd v0.24.0 h1:gL3uHE/IaFj6fcZSu03SvqPMSx7s/dPzfpG/atRwWdo= github.com/btcsuite/btcd v0.24.0/go.mod h1:K4IDc1593s8jKXIF7yS7yCTSxrknB9z0STzc2j6XgE4= github.com/btcsuite/btcd/btcec/v2 v2.1.0/go.mod h1:2VzYrv4Gm4apmbVVsSq5bqf1Ec8v56E48Vt0Y/umPgA= github.com/btcsuite/btcd/btcec/v2 v2.1.3/go.mod h1:ctjw4H1kknNJmRN4iP1R7bTQ+v3GJkZBd6mui8ZsAZE= -github.com/btcsuite/btcd/btcec/v2 v2.3.2 h1:5n0X6hX0Zk+6omWcihdYvdAlGf2DfasC0GMf7DClJ3U= -github.com/btcsuite/btcd/btcec/v2 v2.3.2/go.mod h1:zYzJ8etWJQIv1Ogk7OzpWjowwOdXY1W/17j2MW85J04= +github.com/btcsuite/btcd/btcec/v2 v2.3.3 h1:6+iXlDKE8RMtKsvK0gshlXIuPbyWM/h84Ensb7o3sC0= +github.com/btcsuite/btcd/btcec/v2 v2.3.3/go.mod h1:zYzJ8etWJQIv1Ogk7OzpWjowwOdXY1W/17j2MW85J04= 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.5 h1:+wER79R5670vs/ZusMTF1yTcRYE5GUsFbdjdisflzM8= @@ -28,14 +28,15 @@ github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtE 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= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc= github.com/decred/dcrd/crypto/blake256 v1.0.1 h1:7PltbUIQB7u/FfZ39+DGa/ShuMyJ5ilcvdfma9wOH6Y= github.com/decred/dcrd/crypto/blake256 v1.0.1/go.mod h1:2OfgNZ5wDpcsFmHmCK5gZTPcCXqlm2ArzUIkw9czNJo= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1/go.mod h1:hyedUtir6IdtD/7lIxGeCxkaw7y45JueMRL4DIyJDKs= -github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 h1:8UrgZ3GkP4i/CLijOJx79Yu+etlyjdBU4sfcs2WYQMs= -github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0/go.mod h1:v57UDF4pDQJcEfFUCRop3lJL149eHGSe9Jvczhzjo/0= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 h1:rpfIENRNNilwHwZeG5+P150SMrnNEcHYvcCuK6dPZSg= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0/go.mod h1:v57UDF4pDQJcEfFUCRop3lJL149eHGSe9Jvczhzjo/0= 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= @@ -65,22 +66,23 @@ github.com/onsi/gomega v1.4.1/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5 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/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/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/samber/lo v1.39.0 h1:4gTz1wUhNYLhFSKl6O+8peW0v2F4BCY034GRpU9WnuA= github.com/samber/lo v1.39.0/go.mod h1:+m/ZKRl6ClXCE2Lgf3MsQlWfh4bn1bz6CXEOxnEXnEA= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= -github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= 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/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.20.0 h1:jmAMJJZXr5KiCw05dfYK9QnqaqKLYXijU23lsEdcQqg= -golang.org/x/crypto v0.20.0/go.mod h1:Xwo95rrVNIoSMx9wa1JroENMToLWn3RNVrTBpLHgZPQ= -golang.org/x/exp v0.0.0-20240222234643-814bf88cf225 h1:LfspQV/FYTatPTr/3HzIcmiUFH7PGP+OQ6mgDYo3yuQ= -golang.org/x/exp v0.0.0-20240222234643-814bf88cf225/go.mod h1:CxmFvTBINI24O/j8iY7H1xHzx2i4OsyguNBmN/uPtqc= +golang.org/x/crypto v0.22.0 h1:g1v0xeRhjcugydODzvb3mEM9SQ0HGp9s/nh3COQ/C30= +golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M= +golang.org/x/exp v0.0.0-20240416160154-fe59bbe5cc7f h1:99ci1mjWVBWwJiEKYY6jWa4d2nTQVIEhZIptnrVb1XY= +golang.org/x/exp v0.0.0-20240416160154-fe59bbe5cc7f/go.mod h1:/lliqkxwWAhPjf5oSOIJup2XcqJaw8RGS6k3TGEc7GI= 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= @@ -96,8 +98,8 @@ golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200814200057-3d37ad5750ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y= -golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o= +golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= diff --git a/internal/flags/recovery_flags_test.go b/internal/flags/recovery_flags_test.go index 0ee5e1e..d2957fb 100644 --- a/internal/flags/recovery_flags_test.go +++ b/internal/flags/recovery_flags_test.go @@ -3,7 +3,6 @@ package flags_test import ( "testing" - "github.com/stretchr/testify/require" "github.com/stretchr/testify/suite" "github.com/bitonicnl/verify-signed-message/internal/flags" @@ -21,19 +20,19 @@ func TestRecoveryFlagTestSuite(t *testing.T) { } func (s *RecoveryFlagTestSuite) TestAll() { - require.Equal(s.T(), []int{27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42}, flags.All()) + s.Equal([]int{27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42}, flags.All()) } func (s *RecoveryFlagTestSuite) TestCompressed() { - require.Equal(s.T(), []int{31, 32, 33, 34}, flags.Compressed()) + s.Equal([]int{31, 32, 33, 34}, flags.Compressed()) } func (s *RecoveryFlagTestSuite) TestElectrumP2WPKH() { - require.Equal(s.T(), []int{31, 32, 33, 34}, flags.ElectrumP2WPKH()) + s.Equal([]int{31, 32, 33, 34}, flags.ElectrumP2WPKH()) } func (s *RecoveryFlagTestSuite) TestElectrumP2WPKHAndP2SH() { - require.Equal(s.T(), []int{31, 32, 33, 34}, flags.ElectrumP2WPKHAndP2SH()) + s.Equal([]int{31, 32, 33, 34}, flags.ElectrumP2WPKHAndP2SH()) } func (s *RecoveryFlagTestSuite) TestGetKeyID() { @@ -80,17 +79,17 @@ func (s *RecoveryFlagTestSuite) TestShouldBeCompressed() { } func (s *RecoveryFlagTestSuite) TestTrezor() { - require.Equal(s.T(), []int{35, 36, 37, 38, 39, 40, 41, 42}, flags.Trezor()) + s.Equal([]int{35, 36, 37, 38, 39, 40, 41, 42}, flags.Trezor()) } func (s *RecoveryFlagTestSuite) TestTrezorP2WPKH() { - require.Equal(s.T(), []int{39, 40, 41, 42}, flags.TrezorP2WPKH()) + s.Equal([]int{39, 40, 41, 42}, flags.TrezorP2WPKH()) } func (s *RecoveryFlagTestSuite) TestTrezorP2WPKHAndP2SH() { - require.Equal(s.T(), []int{35, 36, 37, 38}, flags.TrezorP2WPKHAndP2SH()) + s.Equal([]int{35, 36, 37, 38}, flags.TrezorP2WPKHAndP2SH()) } func (s *RecoveryFlagTestSuite) TestUncompressed() { - require.Equal(s.T(), []int{27, 28, 29, 30}, flags.Uncompressed()) + s.Equal([]int{27, 28, 29, 30}, flags.Uncompressed()) } diff --git a/internal/signature/signature_test.go b/internal/signature/signature_test.go index 0a319c5..00d21fe 100644 --- a/internal/signature/signature_test.go +++ b/internal/signature/signature_test.go @@ -9,7 +9,6 @@ import ( "github.com/btcsuite/btcd/btcec/v2" "github.com/btcsuite/btcd/btcec/v2/ecdsa" "github.com/btcsuite/btcd/chaincfg/chainhash" - "github.com/stretchr/testify/require" "github.com/stretchr/testify/suite" "github.com/bitonicnl/verify-signed-message/internal" @@ -47,42 +46,42 @@ func TestServiceTestSuite(t *testing.T) { func (s *SignatureTestSuite) TestParseCompactInvalid() { compactedSignature, err := signature.ParseCompact([]byte{}) - require.EqualError(s.T(), err, "invalid compact signature size") - require.Nil(s.T(), compactedSignature) + s.Require().EqualError(err, "invalid compact signature size") + s.Nil(compactedSignature) } func (s *SignatureTestSuite) TestParseCompact() { compactedSignature, err := signature.ParseCompact(s.signatureEncoded) - require.NoError(s.T(), err) + s.Require().NoError(err) // Retrieve the unexported fields R := s.getFieldFromSignature(compactedSignature, "r") S := s.getFieldFromSignature(compactedSignature, "s") // Ensure they match what we defined - require.Equal(s.T(), "112454100686917088716763005039207074580155840372180209748670933598947425987108", R.String()) - require.Equal(s.T(), "23603267825273168310009216611640910854054822424267934178492474518750065713966", S.String()) + s.Equal("112454100686917088716763005039207074580155840372180209748670933598947425987108", R.String()) + s.Equal("23603267825273168310009216611640910854054822424267934178492474518750065713966", S.String()) } func (s *SignatureTestSuite) TestVerifyInvalidPublicKey() { err := signature.Verify(s.signatureEncoded, &btcec.PublicKey{}, []byte{}) - require.EqualError(s.T(), err, "public key was not correctly instantiated") + s.Require().EqualError(err, "public key was not correctly instantiated") } func (s *SignatureTestSuite) TestVerifyInvalidEncodedSignature() { key, err := btcec.NewPrivateKey() - require.NoError(s.T(), err) + s.Require().NoError(err) err = signature.Verify([]byte{}, key.PubKey(), []byte{}) - require.EqualError(s.T(), err, "invalid compact signature size") + s.Require().EqualError(err, "invalid compact signature size") } func (s *SignatureTestSuite) TestVerifyInvalidSignature() { key, err := btcec.NewPrivateKey() - require.NoError(s.T(), err) + s.Require().NoError(err) err = signature.Verify(s.signatureEncoded, key.PubKey(), []byte{}) - require.EqualError(s.T(), err, "signature could not be verified") + s.Require().EqualError(err, "signature could not be verified") } func (s *SignatureTestSuite) TestVerifyInvalidMessage() { @@ -90,9 +89,9 @@ func (s *SignatureTestSuite) TestVerifyInvalidMessage() { messageHash := chainhash.DoubleHashB([]byte(magicMessage)) publicKey, err := btcec.ParsePubKey(s.publicKeyEncoded) - require.NoError(s.T(), err) + s.Require().NoError(err) - require.EqualError(s.T(), signature.Verify(s.signatureEncoded, publicKey, messageHash), "signature could not be verified") + s.Require().EqualError(signature.Verify(s.signatureEncoded, publicKey, messageHash), "signature could not be verified") } func (s *SignatureTestSuite) TestVerify() { @@ -100,9 +99,9 @@ func (s *SignatureTestSuite) TestVerify() { messageHash := chainhash.DoubleHashB([]byte(magicMessage)) publicKey, err := btcec.ParsePubKey(s.publicKeyEncoded) - require.NoError(s.T(), err) + s.Require().NoError(err) - require.NoError(s.T(), signature.Verify(s.signatureEncoded, publicKey, messageHash)) + s.Require().NoError(signature.Verify(s.signatureEncoded, publicKey, messageHash)) } func (s *SignatureTestSuite) getFieldFromSignature(compactedSignature *ecdsa.Signature, field string) *big.Int { @@ -115,7 +114,7 @@ func (s *SignatureTestSuite) getFieldFromSignature(compactedSignature *ecdsa.Sig // Grab the unexported field rReflected := elem.FieldByName(field) m, ok := reflect.NewAt(rReflected.Type(), unsafe.Pointer(rReflected.UnsafeAddr())).Elem().Interface().(btcec.ModNScalar) - require.True(s.T(), ok) + s.True(ok) // Grab ModNScalar bytes bytes := m.Bytes() diff --git a/internal/validation.go b/internal/validation.go index 09e8e87..e3a42d5 100644 --- a/internal/validation.go +++ b/internal/validation.go @@ -72,11 +72,11 @@ func ValidateP2WPKH(recoveryFlag int, pubkeyHash []byte, addr btcutil.Address, n } // ValidateP2TR ensures that the passed P2TR address matches the address generated from the public key hash, recovery flag and network. +// +// Only addresses without a tapscript are allowed because the verification is using the internal key. func ValidateP2TR(recoveryFlag int, pubKey *btcec.PublicKey, addr btcutil.Address, net *chaincfg.Params) (bool, error) { // Ensure proper address type will be generated - if lo.Contains[int](flags.Compressed(), recoveryFlag) { - return false, errors.New("cannot use P2TR for recovery flag 'compressed'") - } else if lo.Contains[int](flags.TrezorP2WPKHAndP2SH(), recoveryFlag) { + if lo.Contains[int](flags.TrezorP2WPKHAndP2SH(), recoveryFlag) { return false, errors.New("cannot use P2TR for recovery flag 'BIP137 (Trezor) P2WPKH-P2SH'") } else if lo.Contains[int](flags.TrezorP2WPKH(), recoveryFlag) { return false, errors.New("cannot use P2TR for recovery flag 'BIP137 (Trezor) P2WPKH'") diff --git a/internal/validation_test.go b/internal/validation_test.go index b18a7bf..ab7edbe 100644 --- a/internal/validation_test.go +++ b/internal/validation_test.go @@ -2,6 +2,7 @@ package internal_test import ( "crypto/rand" + "encoding/hex" "errors" "testing" @@ -16,11 +17,12 @@ import ( "github.com/bitonicnl/verify-signed-message/internal" ) -// Hash for 1DAag8qiPLHh6hMFVu9qJQm9ro1HtwuyK5, used in this test. -var pubKeyHash = []uint8{133, 113, 93, 2, 177, 222, 121, 165, 69, 34, 61, 182, 122, 239, 165, 136, 229, 124, 167, 194} - type ValidateTestSuite struct { suite.Suite + + legacyPubKeyHash []uint8 + compressedPublicKey *btcec.PublicKey + uncompressedPublicKey *btcec.PublicKey } func TestValidateTestSuite(t *testing.T) { @@ -30,6 +32,17 @@ func TestValidateTestSuite(t *testing.T) { suite.Run(t, new(ValidateTestSuite)) } +func (s *ValidateTestSuite) SetupTest() { + // Compressed legacy public key in bytes (1DAag8qiPLHh6hMFVu9qJQm9ro1HtwuyK5) + s.legacyPubKeyHash = []uint8{133, 113, 93, 2, 177, 222, 121, 165, 69, 34, 61, 182, 122, 239, 165, 136, 229, 124, 167, 194} + + // Compressed taproot public key in hexadecimal format (bc1pgc9k3vdmr9aecmwj09qg5qv550qyyrydufyfmxrsvk5474rxenuqrq4lcz) + s.compressedPublicKey = s.createTaprootPublicKey("0296f45e80c8efdb88b544afde38f2a19d65d40086cff9e2fdd5868d5eb57ca8a6") + + // Uncompressed taproot public key in hexadecimal format (bc1pg48rw0vphy9mght5dr8s5prx92a44wpqmzk67xk8yjf5zlancj9sa3plhc) + s.uncompressedPublicKey = s.createTaprootPublicKey("04c78ea05297a242ba0b2b105bed475b8796fcea30638813f35989c4e0f1df9ef6") +} + func (s *ValidateTestSuite) TestValidateP2PKH() { type args struct { recoveryFlag int @@ -58,12 +71,12 @@ func (s *ValidateTestSuite) TestValidateP2PKH() { }, { name: "Invalid address for public key hash", - args: args{recoveryFlag: 32, pubKeyHash: pubKeyHash, addr: &RandomAddress{Address: "Invalid"}}, + args: args{recoveryFlag: 32, pubKeyHash: s.legacyPubKeyHash, addr: &RandomAddress{Address: "Invalid"}}, want: errors.New("generated address '1DAag8qiPLHh6hMFVu9qJQm9ro1HtwuyK5' does not match expected address 'Invalid'"), }, { name: "Valid P2PKH", - args: args{recoveryFlag: 32, pubKeyHash: pubKeyHash, addr: &RandomAddress{Address: "1DAag8qiPLHh6hMFVu9qJQm9ro1HtwuyK5"}}, + args: args{recoveryFlag: 32, pubKeyHash: s.legacyPubKeyHash, addr: &RandomAddress{Address: "1DAag8qiPLHh6hMFVu9qJQm9ro1HtwuyK5"}}, want: nil, }, } @@ -71,7 +84,7 @@ func (s *ValidateTestSuite) TestValidateP2PKH() { for _, tt := range tests { s.T().Run(tt.name, func(t *testing.T) { _, err := internal.ValidateP2PKH(tt.args.recoveryFlag, tt.args.pubKeyHash, tt.args.addr, &chaincfg.MainNetParams) - require.Equal(t, err, tt.want) + require.Equal(t, tt.want, err) }) } } @@ -79,7 +92,7 @@ func (s *ValidateTestSuite) TestValidateP2PKH() { func (s *ValidateTestSuite) TestValidateP2SH() { pubKeyHashTooLong := make([]uint8, txscript.MaxScriptSize+2) _, err := rand.Read(pubKeyHashTooLong) - require.NoError(s.T(), err) + s.Require().NoError(err) type args struct { recoveryFlag int @@ -108,12 +121,12 @@ func (s *ValidateTestSuite) TestValidateP2SH() { }, { name: "Invalid address for public key hash", - args: args{recoveryFlag: 35, pubKeyHash: pubKeyHash, addr: &RandomAddress{Address: "Invalid"}}, + args: args{recoveryFlag: 35, pubKeyHash: s.legacyPubKeyHash, addr: &RandomAddress{Address: "Invalid"}}, want: errors.New("generated address '3Nxee1CFDqFRtUrixREpNMhsmH9TBXcY48' does not match expected address 'Invalid'"), }, { name: "Valid P2SH", - args: args{recoveryFlag: 35, pubKeyHash: pubKeyHash, addr: &RandomAddress{Address: "3Nxee1CFDqFRtUrixREpNMhsmH9TBXcY48"}}, + args: args{recoveryFlag: 35, pubKeyHash: s.legacyPubKeyHash, addr: &RandomAddress{Address: "3Nxee1CFDqFRtUrixREpNMhsmH9TBXcY48"}}, want: nil, }, } @@ -121,7 +134,7 @@ func (s *ValidateTestSuite) TestValidateP2SH() { for _, tt := range tests { s.T().Run(tt.name, func(t *testing.T) { _, err := internal.ValidateP2SH(tt.args.recoveryFlag, tt.args.pubKeyHash, tt.args.addr, &chaincfg.MainNetParams) - require.Equal(t, err, tt.want) + require.Equal(t, tt.want, err) }) } } @@ -149,12 +162,12 @@ func (s *ValidateTestSuite) TestValidateP2WPKH() { }, { name: "Invalid address for public key hash", - args: args{recoveryFlag: 32, witnessProg: pubKeyHash, addr: &RandomAddress{Address: "Invalid"}}, + args: args{recoveryFlag: 32, witnessProg: s.legacyPubKeyHash, addr: &RandomAddress{Address: "Invalid"}}, want: errors.New("generated address 'bc1qs4c46q43meu623fz8km84ma93rjhef7z88rg99' does not match expected address 'Invalid'"), }, { name: "Valid P2WPKH", - args: args{recoveryFlag: 32, witnessProg: pubKeyHash, addr: &RandomAddress{Address: "bc1qs4c46q43meu623fz8km84ma93rjhef7z88rg99"}}, + args: args{recoveryFlag: 32, witnessProg: s.legacyPubKeyHash, addr: &RandomAddress{Address: "bc1qs4c46q43meu623fz8km84ma93rjhef7z88rg99"}}, want: nil, }, } @@ -162,19 +175,13 @@ func (s *ValidateTestSuite) TestValidateP2WPKH() { for _, tt := range tests { s.T().Run(tt.name, func(t *testing.T) { _, err := internal.ValidateP2WPKH(tt.args.recoveryFlag, tt.args.witnessProg, tt.args.addr, &chaincfg.MainNetParams) - require.Equal(t, err, tt.want) + require.Equal(t, tt.want, err) }) } } +// All addresses were generated via https://demo.unisat.io/ func (s *ValidateTestSuite) TestValidateP2TR() { - // Generated via https://unisat.io/ which uses https://github.com/bitpay/bitcore - x, y := &btcec.FieldVal{}, &btcec.FieldVal{} - x.SetBytes(&[32]byte{199, 142, 160, 82, 151, 162, 66, 186, 11, 43, 16, 91, 237, 71, 91, 135, 150, 252, 234, 48, 99, 136, 19, 243, 89, 137, 196, 224, 241, 223, 158, 246}) - y.SetBytes(&[32]byte{72, 92, 183, 101, 120, 192, 238, 204, 246, 77, 101, 137, 220, 171, 222, 21, 13, 79, 125, 140, 76, 22, 138, 145, 121, 157, 206, 101, 219, 101, 217, 105}) - - pubKey := btcec.NewPublicKey(x, y) - type args struct { recoveryFlag int pubKey *btcec.PublicKey @@ -185,11 +192,6 @@ func (s *ValidateTestSuite) TestValidateP2TR() { args args want error }{ - { - name: "Invalid recovery flag - compressed", - args: args{recoveryFlag: 33, pubKey: &btcec.PublicKey{}, addr: &RandomAddress{}}, - want: errors.New("cannot use P2TR for recovery flag 'compressed'"), - }, { name: "Invalid recovery flag - TrezorP2WPKH", args: args{recoveryFlag: 36, pubKey: &btcec.PublicKey{}, addr: &RandomAddress{}}, @@ -205,14 +207,24 @@ func (s *ValidateTestSuite) TestValidateP2TR() { args: args{recoveryFlag: 27, pubKey: btcec.NewPublicKey(&btcec.FieldVal{}, &btcec.FieldVal{}), addr: &RandomAddress{}}, want: secp256k1.Error{Err: secp256k1.ErrPubKeyNotOnCurve, Description: "invalid public key: x coordinate 0000000000000000000000000000000000000000000000000000000000000000 is not on the secp256k1 curve"}, }, + { + name: "Invalid address for public key - compressed", + args: args{recoveryFlag: 31, pubKey: s.compressedPublicKey, addr: &RandomAddress{Address: "Invalid"}}, + want: errors.New("generated address 'bc1pgc9k3vdmr9aecmwj09qg5qv550qyyrydufyfmxrsvk5474rxenuqrq4lcz' does not match expected address 'Invalid'"), + }, { name: "Invalid address for public key", - args: args{recoveryFlag: 27, pubKey: pubKey, addr: &RandomAddress{Address: "Invalid"}}, + args: args{recoveryFlag: 27, pubKey: s.uncompressedPublicKey, addr: &RandomAddress{Address: "Invalid"}}, want: errors.New("generated address 'bc1pg48rw0vphy9mght5dr8s5prx92a44wpqmzk67xk8yjf5zlancj9sa3plhc' does not match expected address 'Invalid'"), }, + { + name: "Valid P2TR - compressed", + args: args{recoveryFlag: 31, pubKey: s.compressedPublicKey, addr: &RandomAddress{Address: "bc1pgc9k3vdmr9aecmwj09qg5qv550qyyrydufyfmxrsvk5474rxenuqrq4lcz"}}, + want: nil, + }, { name: "Valid P2TR", - args: args{recoveryFlag: 27, pubKey: pubKey, addr: &RandomAddress{Address: "bc1pg48rw0vphy9mght5dr8s5prx92a44wpqmzk67xk8yjf5zlancj9sa3plhc"}}, + args: args{recoveryFlag: 27, pubKey: s.uncompressedPublicKey, addr: &RandomAddress{Address: "bc1pg48rw0vphy9mght5dr8s5prx92a44wpqmzk67xk8yjf5zlancj9sa3plhc"}}, want: nil, }, } @@ -220,11 +232,28 @@ func (s *ValidateTestSuite) TestValidateP2TR() { for _, tt := range tests { s.T().Run(tt.name, func(t *testing.T) { _, err := internal.ValidateP2TR(tt.args.recoveryFlag, tt.args.pubKey, tt.args.addr, &chaincfg.MainNetParams) - require.Equal(t, err, tt.want) + require.Equal(t, tt.want, err) }) } } +func (s *ValidateTestSuite) createTaprootPublicKey(publicKey string) *btcec.PublicKey { + // Convert hexadecimal to bytes + compressedPublicKeyBytes, err := hex.DecodeString(publicKey[2:]) + if err != nil { + s.Require().NoError(err) + } + + // Setup X,Y storage + x, y := &btcec.FieldVal{}, &btcec.FieldVal{} + + // Since taproot uses x-only public keys, only set X + x.SetBytes((*[32]byte)(compressedPublicKeyBytes[:32])) + + // Create a btcd public key + return btcec.NewPublicKey(x, y) +} + // RandomAddress implements the btcutil.Address interface and serves as a no-op to test these calls. type RandomAddress struct { Address string diff --git a/pkg/verify_test.go b/pkg/verify_test.go index 9574880..455d445 100644 --- a/pkg/verify_test.go +++ b/pkg/verify_test.go @@ -5,7 +5,6 @@ import ( "testing" "github.com/btcsuite/btcd/chaincfg" - "github.com/stretchr/testify/assert" "github.com/stretchr/testify/suite" verifier "github.com/bitonicnl/verify-signed-message/pkg" @@ -125,8 +124,8 @@ func (s *VerifyTestSuite) TestVerifyIncorrect() { for name, tt := range tests { s.Run(name, func() { valid, err := verifier.Verify(tt.signedMessage) - assert.EqualError(s.T(), err, tt.expectedError) - assert.False(s.T(), valid) + s.False(valid) + s.Require().EqualError(err, tt.expectedError) }) } } @@ -149,9 +148,9 @@ func (s *VerifyTestSuite) TestVerifyWithChainTestnet() { for name, tt := range tests { s.Run(name, func() { - if valid, err := verifier.VerifyWithChain(tt, &chaincfg.TestNet3Params); assert.NoError(s.T(), err) { - assert.True(s.T(), valid) - } + valid, err := verifier.VerifyWithChain(tt, &chaincfg.TestNet3Params) + s.Require().NoError(err) + s.True(valid) }) } } @@ -330,9 +329,9 @@ func (s *VerifyTestSuite) TestVerify() { for i := range tests { s.Run(i, func() { - if valid, err := verifier.Verify(tests[i]); assert.NoError(s.T(), err) { - assert.True(s.T(), valid) - } + valid, err := verifier.Verify(tests[i]) + s.Require().NoError(err) + s.True(valid) }) } }