mirror of
https://gitlab.com/pulsechaincom/prysm-pulse.git
synced 2024-12-22 03:30:35 +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/comparesame:go_tool_library",
|
||||
"//tools/analyzers/shadowpredecl:go_tool_library",
|
||||
"//tools/analyzers/nop:go_tool_library",
|
||||
] + select({
|
||||
# nogo checks that fail with coverage enabled.
|
||||
":coverage_enabled": [],
|
||||
|
@ -123,5 +123,12 @@
|
||||
"rules_go_work-.*": "Third party code",
|
||||
"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.
|
||||
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
|
||||
|
@ -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.
|
||||
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 (
|
||||
"errors"
|
||||
"testing"
|
||||
|
||||
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/testutil/assert"
|
||||
"github.com/prysmaticlabs/prysm/shared/testutil/require"
|
||||
)
|
||||
|
||||
func TestSignVerify(t *testing.T) {
|
||||
priv := herumi.RandKey()
|
||||
priv := RandKey()
|
||||
pub := priv.PublicKey()
|
||||
msg := []byte("hello")
|
||||
sig := priv.Sign(msg)
|
||||
@ -25,14 +24,14 @@ func TestAggregateVerify(t *testing.T) {
|
||||
var msgs [][32]byte
|
||||
for i := 0; i < 100; i++ {
|
||||
msg := [32]byte{'h', 'e', 'l', 'l', 'o', byte(i)}
|
||||
priv := herumi.RandKey()
|
||||
priv := RandKey()
|
||||
pub := priv.PublicKey()
|
||||
sig := priv.Sign(msg[:])
|
||||
pubkeys = append(pubkeys, pub)
|
||||
sigs = append(sigs, sig)
|
||||
msgs = append(msgs, msg)
|
||||
}
|
||||
aggSig := herumi.Aggregate(sigs)
|
||||
aggSig := Aggregate(sigs)
|
||||
assert.DeepEqual(t, true, aggSig.AggregateVerify(pubkeys, msgs))
|
||||
}
|
||||
|
||||
@ -41,13 +40,13 @@ func TestFastAggregateVerify(t *testing.T) {
|
||||
sigs := make([]iface.Signature, 0, 100)
|
||||
msg := [32]byte{'h', 'e', 'l', 'l', 'o'}
|
||||
for i := 0; i < 100; i++ {
|
||||
priv := herumi.RandKey()
|
||||
priv := RandKey()
|
||||
pub := priv.PublicKey()
|
||||
sig := priv.Sign(msg[:])
|
||||
pubkeys = append(pubkeys, pub)
|
||||
sigs = append(sigs, sig)
|
||||
}
|
||||
aggSig := herumi.AggregateSignatures(sigs)
|
||||
aggSig := AggregateSignatures(sigs)
|
||||
assert.DeepEqual(t, true, aggSig.FastAggregateVerify(pubkeys, msg))
|
||||
}
|
||||
|
||||
@ -57,14 +56,14 @@ func TestMultipleSignatureVerification(t *testing.T) {
|
||||
var msgs [][32]byte
|
||||
for i := 0; i < 100; i++ {
|
||||
msg := [32]byte{'h', 'e', 'l', 'l', 'o', byte(i)}
|
||||
priv := herumi.RandKey()
|
||||
priv := RandKey()
|
||||
pub := priv.PublicKey()
|
||||
sig := priv.Sign(msg[:])
|
||||
pubkeys = append(pubkeys, pub)
|
||||
sigs = append(sigs, sig)
|
||||
msgs = append(msgs, msg)
|
||||
}
|
||||
verify, err := herumi.VerifyMultipleSignatures(sigs, msgs, pubkeys)
|
||||
verify, err := VerifyMultipleSignatures(sigs, msgs, pubkeys)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, true, verify, "Signature did not verify")
|
||||
}
|
||||
@ -75,7 +74,7 @@ func TestMultipleSignatureVerification_FailsCorrectly(t *testing.T) {
|
||||
var msgs [][32]byte
|
||||
for i := 0; i < 100; i++ {
|
||||
msg := [32]byte{'h', 'e', 'l', 'l', 'o', byte(i)}
|
||||
priv := herumi.RandKey()
|
||||
priv := RandKey()
|
||||
pub := priv.PublicKey()
|
||||
sig := priv.Sign(msg[:])
|
||||
pubkeys = append(pubkeys, pub)
|
||||
@ -113,21 +112,21 @@ func TestMultipleSignatureVerification_FailsCorrectly(t *testing.T) {
|
||||
bls12.G2Add(firstG2, firstG2, g2Point)
|
||||
bls12.G2Sub(secondG2, secondG2, g2Point)
|
||||
|
||||
lastSig, err := herumi.SignatureFromBytes(rawSig.Serialize())
|
||||
lastSig, err := SignatureFromBytes(rawSig.Serialize())
|
||||
require.NoError(t, err)
|
||||
secondLastSig, err = herumi.SignatureFromBytes(rawSig2.Serialize())
|
||||
secondLastSig, err = SignatureFromBytes(rawSig2.Serialize())
|
||||
require.NoError(t, err)
|
||||
sigs[len(sigs)-1] = lastSig
|
||||
sigs[len(sigs)-2] = secondLastSig
|
||||
|
||||
// This method is expected to pass, as it would not
|
||||
// be able to detect bad signatures
|
||||
aggSig := herumi.AggregateSignatures(sigs)
|
||||
aggSig := AggregateSignatures(sigs)
|
||||
if !aggSig.AggregateVerify(pubkeys, msgs) {
|
||||
t.Error("Signature did not verify")
|
||||
}
|
||||
// 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.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
|
||||
msg := [32]byte{'h', 'e', 'l', 'l', 'o'}
|
||||
|
||||
aggSig := herumi.NewAggregateSignature()
|
||||
aggSig := NewAggregateSignature()
|
||||
if aggSig.FastAggregateVerify(pubkeys, msg) != false {
|
||||
t.Error("Expected FastAggregateVerify to return false with empty input " +
|
||||
"of public keys.")
|
||||
@ -181,7 +180,7 @@ func TestSignatureFromBytes(t *testing.T) {
|
||||
|
||||
for _, test := range tests {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
res, err := herumi.SignatureFromBytes(test.input)
|
||||
res, err := SignatureFromBytes(test.input)
|
||||
if test.err != nil {
|
||||
assert.ErrorContains(t, test.err.Error(), err)
|
||||
} 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