mirror of
https://gitlab.com/pulsechaincom/prysm-pulse.git
synced 2025-01-03 00:27:38 +00:00
No-op Instruction analyzer (#7249)
* analyzer, tests and fixes * error check * gazelle * add more asserts * Merge branch 'master' into nop-analyzer * Merge refs/heads/master into nop-analyzer * fix no-op in blst package * Merge refs/heads/master into nop-analyzer * add assert after mutation * mark test as TODO * add issue number to TODO
This commit is contained in:
parent
e1e233a6d0
commit
a2cf235687
@ -110,6 +110,7 @@ nogo(
|
|||||||
"//tools/analyzers/featureconfig:go_tool_library",
|
"//tools/analyzers/featureconfig:go_tool_library",
|
||||||
"//tools/analyzers/comparesame:go_tool_library",
|
"//tools/analyzers/comparesame:go_tool_library",
|
||||||
"//tools/analyzers/shadowpredecl:go_tool_library",
|
"//tools/analyzers/shadowpredecl:go_tool_library",
|
||||||
|
"//tools/analyzers/nop:go_tool_library",
|
||||||
] + select({
|
] + select({
|
||||||
# nogo checks that fail with coverage enabled.
|
# nogo checks that fail with coverage enabled.
|
||||||
":coverage_enabled": [],
|
":coverage_enabled": [],
|
||||||
|
@ -123,5 +123,12 @@
|
|||||||
"rules_go_work-.*": "Third party code",
|
"rules_go_work-.*": "Third party code",
|
||||||
"tools/analyzers/shadowpredecl/testdata/shadow.go": "Analyzer testdata has to break rules"
|
"tools/analyzers/shadowpredecl/testdata/shadow.go": "Analyzer testdata has to break rules"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"nop": {
|
||||||
|
"exclude_files": {
|
||||||
|
"external/.*": "Third party code",
|
||||||
|
"rules_go_work-.*": "Third party code",
|
||||||
|
"tools/analyzers/nop/testdata/no_op.go": "Analyzer testdata has to break rules"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -205,7 +205,8 @@ func (s *Signature) Marshal() []byte {
|
|||||||
|
|
||||||
// Copy returns a full deep copy of a signature.
|
// Copy returns a full deep copy of a signature.
|
||||||
func (s *Signature) Copy() iface.Signature {
|
func (s *Signature) Copy() iface.Signature {
|
||||||
return &Signature{s: &*s.s}
|
sign := *s.s
|
||||||
|
return &Signature{s: &sign}
|
||||||
}
|
}
|
||||||
|
|
||||||
// VerifyCompressed verifies that the compressed signature and pubkey
|
// VerifyCompressed verifies that the compressed signature and pubkey
|
||||||
|
@ -137,3 +137,18 @@ func TestSignatureFromBytes(t *testing.T) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO(7249): Make this test work
|
||||||
|
/*func TestCopy(t *testing.T) {
|
||||||
|
key := RandKey().(*bls12SecretKey)
|
||||||
|
signatureA := &Signature{s: new(blstSignature).Sign(key.p, []byte("foo"), dst)}
|
||||||
|
signatureB, ok := signatureA.Copy().(*Signature)
|
||||||
|
require.Equal(t, true, ok)
|
||||||
|
|
||||||
|
assert.NotEqual(t, signatureA, signatureB)
|
||||||
|
assert.NotEqual(t, signatureA.s, signatureB.s)
|
||||||
|
assert.DeepEqual(t, signatureA, signatureB)
|
||||||
|
|
||||||
|
signatureA.s = new(blstSignature).Sign(key.p, []byte("bar"), dst)
|
||||||
|
assert.DeepNotEqual(t, signatureA, signatureB)
|
||||||
|
}*/
|
||||||
|
@ -210,5 +210,6 @@ func (s *Signature) Marshal() []byte {
|
|||||||
|
|
||||||
// Copy returns a full deep copy of a signature.
|
// Copy returns a full deep copy of a signature.
|
||||||
func (s *Signature) Copy() iface.Signature {
|
func (s *Signature) Copy() iface.Signature {
|
||||||
return &Signature{s: &*s.s}
|
sign := *s.s
|
||||||
|
return &Signature{s: &sign}
|
||||||
}
|
}
|
||||||
|
@ -1,18 +1,17 @@
|
|||||||
package herumi_test
|
package herumi
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
bls12 "github.com/herumi/bls-eth-go-binary/bls"
|
bls12 "github.com/herumi/bls-eth-go-binary/bls"
|
||||||
"github.com/prysmaticlabs/prysm/shared/bls/herumi"
|
|
||||||
"github.com/prysmaticlabs/prysm/shared/bls/iface"
|
"github.com/prysmaticlabs/prysm/shared/bls/iface"
|
||||||
"github.com/prysmaticlabs/prysm/shared/testutil/assert"
|
"github.com/prysmaticlabs/prysm/shared/testutil/assert"
|
||||||
"github.com/prysmaticlabs/prysm/shared/testutil/require"
|
"github.com/prysmaticlabs/prysm/shared/testutil/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestSignVerify(t *testing.T) {
|
func TestSignVerify(t *testing.T) {
|
||||||
priv := herumi.RandKey()
|
priv := RandKey()
|
||||||
pub := priv.PublicKey()
|
pub := priv.PublicKey()
|
||||||
msg := []byte("hello")
|
msg := []byte("hello")
|
||||||
sig := priv.Sign(msg)
|
sig := priv.Sign(msg)
|
||||||
@ -25,14 +24,14 @@ func TestAggregateVerify(t *testing.T) {
|
|||||||
var msgs [][32]byte
|
var msgs [][32]byte
|
||||||
for i := 0; i < 100; i++ {
|
for i := 0; i < 100; i++ {
|
||||||
msg := [32]byte{'h', 'e', 'l', 'l', 'o', byte(i)}
|
msg := [32]byte{'h', 'e', 'l', 'l', 'o', byte(i)}
|
||||||
priv := herumi.RandKey()
|
priv := RandKey()
|
||||||
pub := priv.PublicKey()
|
pub := priv.PublicKey()
|
||||||
sig := priv.Sign(msg[:])
|
sig := priv.Sign(msg[:])
|
||||||
pubkeys = append(pubkeys, pub)
|
pubkeys = append(pubkeys, pub)
|
||||||
sigs = append(sigs, sig)
|
sigs = append(sigs, sig)
|
||||||
msgs = append(msgs, msg)
|
msgs = append(msgs, msg)
|
||||||
}
|
}
|
||||||
aggSig := herumi.Aggregate(sigs)
|
aggSig := Aggregate(sigs)
|
||||||
assert.DeepEqual(t, true, aggSig.AggregateVerify(pubkeys, msgs))
|
assert.DeepEqual(t, true, aggSig.AggregateVerify(pubkeys, msgs))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -41,13 +40,13 @@ func TestFastAggregateVerify(t *testing.T) {
|
|||||||
sigs := make([]iface.Signature, 0, 100)
|
sigs := make([]iface.Signature, 0, 100)
|
||||||
msg := [32]byte{'h', 'e', 'l', 'l', 'o'}
|
msg := [32]byte{'h', 'e', 'l', 'l', 'o'}
|
||||||
for i := 0; i < 100; i++ {
|
for i := 0; i < 100; i++ {
|
||||||
priv := herumi.RandKey()
|
priv := RandKey()
|
||||||
pub := priv.PublicKey()
|
pub := priv.PublicKey()
|
||||||
sig := priv.Sign(msg[:])
|
sig := priv.Sign(msg[:])
|
||||||
pubkeys = append(pubkeys, pub)
|
pubkeys = append(pubkeys, pub)
|
||||||
sigs = append(sigs, sig)
|
sigs = append(sigs, sig)
|
||||||
}
|
}
|
||||||
aggSig := herumi.AggregateSignatures(sigs)
|
aggSig := AggregateSignatures(sigs)
|
||||||
assert.DeepEqual(t, true, aggSig.FastAggregateVerify(pubkeys, msg))
|
assert.DeepEqual(t, true, aggSig.FastAggregateVerify(pubkeys, msg))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -57,14 +56,14 @@ func TestMultipleSignatureVerification(t *testing.T) {
|
|||||||
var msgs [][32]byte
|
var msgs [][32]byte
|
||||||
for i := 0; i < 100; i++ {
|
for i := 0; i < 100; i++ {
|
||||||
msg := [32]byte{'h', 'e', 'l', 'l', 'o', byte(i)}
|
msg := [32]byte{'h', 'e', 'l', 'l', 'o', byte(i)}
|
||||||
priv := herumi.RandKey()
|
priv := RandKey()
|
||||||
pub := priv.PublicKey()
|
pub := priv.PublicKey()
|
||||||
sig := priv.Sign(msg[:])
|
sig := priv.Sign(msg[:])
|
||||||
pubkeys = append(pubkeys, pub)
|
pubkeys = append(pubkeys, pub)
|
||||||
sigs = append(sigs, sig)
|
sigs = append(sigs, sig)
|
||||||
msgs = append(msgs, msg)
|
msgs = append(msgs, msg)
|
||||||
}
|
}
|
||||||
verify, err := herumi.VerifyMultipleSignatures(sigs, msgs, pubkeys)
|
verify, err := VerifyMultipleSignatures(sigs, msgs, pubkeys)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Equal(t, true, verify, "Signature did not verify")
|
assert.Equal(t, true, verify, "Signature did not verify")
|
||||||
}
|
}
|
||||||
@ -75,7 +74,7 @@ func TestMultipleSignatureVerification_FailsCorrectly(t *testing.T) {
|
|||||||
var msgs [][32]byte
|
var msgs [][32]byte
|
||||||
for i := 0; i < 100; i++ {
|
for i := 0; i < 100; i++ {
|
||||||
msg := [32]byte{'h', 'e', 'l', 'l', 'o', byte(i)}
|
msg := [32]byte{'h', 'e', 'l', 'l', 'o', byte(i)}
|
||||||
priv := herumi.RandKey()
|
priv := RandKey()
|
||||||
pub := priv.PublicKey()
|
pub := priv.PublicKey()
|
||||||
sig := priv.Sign(msg[:])
|
sig := priv.Sign(msg[:])
|
||||||
pubkeys = append(pubkeys, pub)
|
pubkeys = append(pubkeys, pub)
|
||||||
@ -113,21 +112,21 @@ func TestMultipleSignatureVerification_FailsCorrectly(t *testing.T) {
|
|||||||
bls12.G2Add(firstG2, firstG2, g2Point)
|
bls12.G2Add(firstG2, firstG2, g2Point)
|
||||||
bls12.G2Sub(secondG2, secondG2, g2Point)
|
bls12.G2Sub(secondG2, secondG2, g2Point)
|
||||||
|
|
||||||
lastSig, err := herumi.SignatureFromBytes(rawSig.Serialize())
|
lastSig, err := SignatureFromBytes(rawSig.Serialize())
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
secondLastSig, err = herumi.SignatureFromBytes(rawSig2.Serialize())
|
secondLastSig, err = SignatureFromBytes(rawSig2.Serialize())
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
sigs[len(sigs)-1] = lastSig
|
sigs[len(sigs)-1] = lastSig
|
||||||
sigs[len(sigs)-2] = secondLastSig
|
sigs[len(sigs)-2] = secondLastSig
|
||||||
|
|
||||||
// This method is expected to pass, as it would not
|
// This method is expected to pass, as it would not
|
||||||
// be able to detect bad signatures
|
// be able to detect bad signatures
|
||||||
aggSig := herumi.AggregateSignatures(sigs)
|
aggSig := AggregateSignatures(sigs)
|
||||||
if !aggSig.AggregateVerify(pubkeys, msgs) {
|
if !aggSig.AggregateVerify(pubkeys, msgs) {
|
||||||
t.Error("Signature did not verify")
|
t.Error("Signature did not verify")
|
||||||
}
|
}
|
||||||
// This method would be expected to fail.
|
// This method would be expected to fail.
|
||||||
verify, err := herumi.VerifyMultipleSignatures(sigs, msgs, pubkeys)
|
verify, err := VerifyMultipleSignatures(sigs, msgs, pubkeys)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Equal(t, false, verify, "Signature verified when it was not supposed to")
|
assert.Equal(t, false, verify, "Signature verified when it was not supposed to")
|
||||||
}
|
}
|
||||||
@ -136,7 +135,7 @@ func TestFastAggregateVerify_ReturnsFalseOnEmptyPubKeyList(t *testing.T) {
|
|||||||
var pubkeys []iface.PublicKey
|
var pubkeys []iface.PublicKey
|
||||||
msg := [32]byte{'h', 'e', 'l', 'l', 'o'}
|
msg := [32]byte{'h', 'e', 'l', 'l', 'o'}
|
||||||
|
|
||||||
aggSig := herumi.NewAggregateSignature()
|
aggSig := NewAggregateSignature()
|
||||||
if aggSig.FastAggregateVerify(pubkeys, msg) != false {
|
if aggSig.FastAggregateVerify(pubkeys, msg) != false {
|
||||||
t.Error("Expected FastAggregateVerify to return false with empty input " +
|
t.Error("Expected FastAggregateVerify to return false with empty input " +
|
||||||
"of public keys.")
|
"of public keys.")
|
||||||
@ -181,7 +180,7 @@ func TestSignatureFromBytes(t *testing.T) {
|
|||||||
|
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
t.Run(test.name, func(t *testing.T) {
|
t.Run(test.name, func(t *testing.T) {
|
||||||
res, err := herumi.SignatureFromBytes(test.input)
|
res, err := SignatureFromBytes(test.input)
|
||||||
if test.err != nil {
|
if test.err != nil {
|
||||||
assert.ErrorContains(t, test.err.Error(), err)
|
assert.ErrorContains(t, test.err.Error(), err)
|
||||||
} else {
|
} else {
|
||||||
@ -191,3 +190,16 @@ func TestSignatureFromBytes(t *testing.T) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestCopy(t *testing.T) {
|
||||||
|
signatureA := &Signature{s: bls12.HashAndMapToSignature([]byte("foo"))}
|
||||||
|
signatureB, ok := signatureA.Copy().(*Signature)
|
||||||
|
require.Equal(t, true, ok)
|
||||||
|
|
||||||
|
assert.NotEqual(t, signatureA, signatureB)
|
||||||
|
assert.NotEqual(t, signatureA.s, signatureB.s)
|
||||||
|
assert.DeepEqual(t, signatureA, signatureB)
|
||||||
|
|
||||||
|
signatureA.s.Add(bls12.HashAndMapToSignature([]byte("bar")))
|
||||||
|
assert.DeepNotEqual(t, signatureA, signatureB)
|
||||||
|
}
|
||||||
|
28
tools/analyzers/nop/BUILD.bazel
Normal file
28
tools/analyzers/nop/BUILD.bazel
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
load("@prysm//tools/go:def.bzl", "go_library")
|
||||||
|
load("@io_bazel_rules_go//go:def.bzl", "go_tool_library")
|
||||||
|
|
||||||
|
go_library(
|
||||||
|
name = "go_default_library",
|
||||||
|
srcs = ["analyzer.go"],
|
||||||
|
importpath = "github.com/prysmaticlabs/prysm/tools/analyzers/nop",
|
||||||
|
visibility = ["//visibility:public"],
|
||||||
|
deps = [
|
||||||
|
"@org_golang_x_tools//go/analysis:go_default_library",
|
||||||
|
"@org_golang_x_tools//go/analysis/passes/inspect:go_default_library",
|
||||||
|
"@org_golang_x_tools//go/ast/inspector:go_default_library",
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
|
go_tool_library(
|
||||||
|
name = "go_tool_library",
|
||||||
|
srcs = ["analyzer.go"],
|
||||||
|
importpath = "github.com/prysmaticlabs/prysm/tools/analyzers/nop",
|
||||||
|
visibility = ["//visibility:public"],
|
||||||
|
deps = [
|
||||||
|
"@org_golang_x_tools//go/analysis:go_tool_library",
|
||||||
|
"@org_golang_x_tools//go/analysis/passes/inspect:go_tool_library",
|
||||||
|
"@org_golang_x_tools//go/ast/inspector:go_tool_library",
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
|
# gazelle:exclude analyzer_test.go
|
59
tools/analyzers/nop/analyzer.go
Normal file
59
tools/analyzers/nop/analyzer.go
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
package nop
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"go/ast"
|
||||||
|
"go/token"
|
||||||
|
|
||||||
|
"golang.org/x/tools/go/analysis"
|
||||||
|
"golang.org/x/tools/go/analysis/passes/inspect"
|
||||||
|
"golang.org/x/tools/go/ast/inspector"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Doc explaining the tool.
|
||||||
|
const Doc = "Tool to detect no-op instructions."
|
||||||
|
|
||||||
|
const message = "Found a no-op instruction that can be safely removed. " +
|
||||||
|
"It might be a result of writing code that does not do what was intended."
|
||||||
|
|
||||||
|
// Analyzer runs static analysis.
|
||||||
|
var Analyzer = &analysis.Analyzer{
|
||||||
|
Name: "nop",
|
||||||
|
Doc: Doc,
|
||||||
|
Requires: []*analysis.Analyzer{inspect.Analyzer},
|
||||||
|
Run: run,
|
||||||
|
}
|
||||||
|
|
||||||
|
func run(pass *analysis.Pass) (interface{}, error) {
|
||||||
|
inspect, ok := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector)
|
||||||
|
if !ok {
|
||||||
|
return nil, errors.New("analyzer is not type *inspector.Inspector")
|
||||||
|
}
|
||||||
|
|
||||||
|
nodeFilter := []ast.Node{
|
||||||
|
(*ast.StarExpr)(nil),
|
||||||
|
(*ast.UnaryExpr)(nil),
|
||||||
|
}
|
||||||
|
|
||||||
|
inspect.Preorder(nodeFilter, func(node ast.Node) {
|
||||||
|
switch expr := node.(type) {
|
||||||
|
case *ast.StarExpr:
|
||||||
|
unaryExpr, ok := expr.X.(*ast.UnaryExpr)
|
||||||
|
if !ok {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if unaryExpr.Op == token.AND {
|
||||||
|
pass.Reportf(expr.Star, message)
|
||||||
|
}
|
||||||
|
case *ast.UnaryExpr:
|
||||||
|
if expr.Op == token.AND {
|
||||||
|
if _, ok := expr.X.(*ast.StarExpr); ok {
|
||||||
|
pass.Reportf(expr.OpPos, message)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
return nil, nil
|
||||||
|
}
|
11
tools/analyzers/nop/analyzer_test.go
Normal file
11
tools/analyzers/nop/analyzer_test.go
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
package nop
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"golang.org/x/tools/go/analysis/analysistest"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestAnalyzer(t *testing.T) {
|
||||||
|
analysistest.Run(t, analysistest.TestData(), Analyzer)
|
||||||
|
}
|
8
tools/analyzers/nop/testdata/BUILD.bazel
vendored
Normal file
8
tools/analyzers/nop/testdata/BUILD.bazel
vendored
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
load("@prysm//tools/go:def.bzl", "go_library")
|
||||||
|
|
||||||
|
go_library(
|
||||||
|
name = "go_default_library",
|
||||||
|
srcs = ["no_op.go"],
|
||||||
|
importpath = "github.com/prysmaticlabs/prysm/tools/analyzers/nop/testdata",
|
||||||
|
visibility = ["//visibility:public"],
|
||||||
|
)
|
14
tools/analyzers/nop/testdata/no_op.go
vendored
Normal file
14
tools/analyzers/nop/testdata/no_op.go
vendored
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
package testdata
|
||||||
|
|
||||||
|
type foo struct {
|
||||||
|
}
|
||||||
|
|
||||||
|
func AddressOfDereferencedValue() {
|
||||||
|
x := &foo{}
|
||||||
|
_ = &*x // want "Found a no-op instruction that can be safely removed. It might be a result of writing code that does not work as expected."
|
||||||
|
}
|
||||||
|
|
||||||
|
func DereferencedAddressOfValue() {
|
||||||
|
x := foo{}
|
||||||
|
_ = *&x // want "Found a no-op instruction that can be safely removed. It might be a result of writing code that does not work as expected."
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user