github.com/line/ostracon@v1.0.10-0.20230328032236-7f20145f065d/test/kms/bench_test.go (about)

     1  // This program performs tests and benchmarks that SignerClient can connect to KMS and make API calls.
     2  // To test, address the KMS connection to port 45666 on the machine running this program and run the following:
     3  //
     4  // $ cd test/kms
     5  // $ go test -tags libsodium -bench . -benchmem
     6  package main
     7  
     8  import (
     9  	"net"
    10  	"os"
    11  	"testing"
    12  	"time"
    13  
    14  	"github.com/stretchr/testify/require"
    15  
    16  	privvalproto "github.com/tendermint/tendermint/proto/tendermint/privval"
    17  	"github.com/tendermint/tendermint/proto/tendermint/types"
    18  
    19  	"github.com/line/ostracon/config"
    20  	"github.com/line/ostracon/crypto"
    21  	"github.com/line/ostracon/crypto/ed25519"
    22  	"github.com/line/ostracon/crypto/vrf"
    23  	"github.com/line/ostracon/libs/log"
    24  	tmnet "github.com/line/ostracon/libs/net"
    25  	"github.com/line/ostracon/node"
    26  	"github.com/line/ostracon/privval"
    27  	ocprivvalproto "github.com/line/ostracon/proto/ostracon/privval"
    28  	octypes "github.com/line/ostracon/types"
    29  )
    30  
    31  var logger = log.NewOCLogger(log.NewSyncWriter(os.Stdout))
    32  
    33  const chainID = "test-chain"
    34  const listenAddr = "tcp://0.0.0.0:45666"
    35  
    36  func BenchmarkKMS(b *testing.B) {
    37  	chainID := "test-chain"
    38  	protocol, address := tmnet.ProtocolAndAddress(listenAddr)
    39  	ln, err := net.Listen(protocol, address)
    40  	require.NoError(b, err)
    41  	listener := privval.NewTCPListener(ln, ed25519.GenPrivKeyFromSecret([]byte("🏺")))
    42  	endpoint := privval.NewSignerListenerEndpoint(logger, listener)
    43  	client, err := privval.NewSignerClient(endpoint, chainID)
    44  	require.NoError(b, err)
    45  
    46  	// ensure connection and warm up
    47  	b.Run("Ping", func(b *testing.B) {
    48  		b.ResetTimer()
    49  		for i := 0; i < b.N; i++ {
    50  			ping(endpoint)
    51  		}
    52  		b.StopTimer()
    53  	})
    54  
    55  	benchmarkPrivValidator(b, client)
    56  }
    57  
    58  func BenchmarkFilePV(b *testing.B) {
    59  	cfg := config.ResetTestRoot("BenchmarkFilePV")
    60  	defer func() {
    61  		var _ = os.RemoveAll(cfg.RootDir)
    62  	}()
    63  
    64  	n, err := node.NewOstraconNode(cfg, logger)
    65  	require.NoError(b, err)
    66  
    67  	benchmarkPrivValidator(b, n.PrivValidator())
    68  }
    69  
    70  func benchmarkPrivValidator(b *testing.B, pv octypes.PrivValidator) {
    71  	pubKey := benchmarkGetPubKey(b, pv)
    72  	benchmarkSignVote(b, pv, pubKey)
    73  	benchmarkSignProposal(b, pv, pubKey)
    74  	benchmarkVRFProof(b, pv, pubKey)
    75  }
    76  
    77  func benchmarkGetPubKey(b *testing.B, pv octypes.PrivValidator) crypto.PubKey {
    78  	var pubKey crypto.PubKey
    79  	var err error
    80  
    81  	// performance measurement
    82  	b.Run("GetPubKey", func(b *testing.B) {
    83  		for i := 0; i < b.N; i++ {
    84  			pubKey, err = pv.GetPubKey()
    85  		}
    86  	})
    87  
    88  	// evaluate execution results
    89  	require.NoError(b, err)
    90  	require.Equalf(b, ed25519.PubKeySize, len(pubKey.Bytes()), "PubKey: public key size = %d != %d",
    91  		ed25519.PubKeySize, len(pubKey.Bytes()))
    92  	return pubKey
    93  }
    94  
    95  func benchmarkSignVote(b *testing.B, pv octypes.PrivValidator, pubKey crypto.PubKey) {
    96  	blockID := octypes.BlockID{
    97  		Hash: make([]byte, 32),
    98  		PartSetHeader: octypes.PartSetHeader{
    99  			Total: 10,
   100  			Hash:  make([]byte, 32),
   101  		},
   102  	}
   103  	vote := octypes.Vote{
   104  		Type:             types.PrevoteType,
   105  		Height:           1,
   106  		Round:            0,
   107  		BlockID:          blockID,
   108  		Timestamp:        time.Now(),
   109  		ValidatorAddress: pubKey.Address(),
   110  		ValidatorIndex:   0,
   111  		Signature:        nil,
   112  	}
   113  	pb := vote.ToProto()
   114  	var err error
   115  
   116  	// performance measurement
   117  	b.Run("SignVote", func(b *testing.B) {
   118  		for i := 0; i < b.N; i++ {
   119  			err = pv.SignVote(chainID, pb)
   120  		}
   121  	})
   122  
   123  	// evaluate execution results
   124  	require.NoError(b, err)
   125  	require.Equalf(b, ed25519.SignatureSize, len(pb.Signature), "SignVote: signature size = %d != %d",
   126  		ed25519.SignatureSize, len(pb.Signature))
   127  	bytes := octypes.VoteSignBytes(chainID, pb)
   128  	require.Truef(b, pubKey.VerifySignature(bytes, pb.Signature), "SignVote: signature verification")
   129  }
   130  
   131  func benchmarkSignProposal(b *testing.B, pv octypes.PrivValidator, pubKey crypto.PubKey) {
   132  	blockID := octypes.BlockID{
   133  		Hash: make([]byte, 32),
   134  		PartSetHeader: octypes.PartSetHeader{
   135  			Total: 10,
   136  			Hash:  make([]byte, 32),
   137  		},
   138  	}
   139  	proposal := octypes.Proposal{
   140  		Type:      types.ProposalType,
   141  		Height:    2,
   142  		Round:     0,
   143  		POLRound:  -1,
   144  		BlockID:   blockID,
   145  		Timestamp: time.Now(),
   146  		Signature: nil,
   147  	}
   148  	pb := proposal.ToProto()
   149  	var err error
   150  
   151  	// performance measurement
   152  	b.Run("SignProposal", func(b *testing.B) {
   153  		for i := 0; i < b.N; i++ {
   154  			err = pv.SignProposal(chainID, pb)
   155  		}
   156  	})
   157  
   158  	// evaluate execution results
   159  	require.NoError(b, err)
   160  	require.Equalf(b, ed25519.SignatureSize, len(pb.Signature), "SignProposal: signature size = %d != %d",
   161  		ed25519.SignatureSize, len(pb.Signature))
   162  	bytes := octypes.ProposalSignBytes(chainID, pb)
   163  	require.Truef(b, pubKey.VerifySignature(bytes, pb.Signature), "SignProposal: signature verification")
   164  }
   165  
   166  func benchmarkVRFProof(b *testing.B, pv octypes.PrivValidator, pubKey crypto.PubKey) {
   167  	message := []byte("hello, world")
   168  	var proof crypto.Proof
   169  	var err error
   170  
   171  	// performance measurement
   172  	b.Run("VRFProof", func(b *testing.B) {
   173  		for i := 0; i < b.N; i++ {
   174  			proof, err = pv.GenerateVRFProof(message)
   175  		}
   176  	})
   177  
   178  	// evaluate execution results
   179  	require.NoError(b, err)
   180  	require.Equalf(b, vrf.ProofSize, len(proof), "VRFProof: proof size = %d != %d", len(proof), vrf.ProofSize)
   181  	output, err := pubKey.VRFVerify(proof, message)
   182  	require.NoError(b, err)
   183  	require.Equalf(b, vrf.OutputSize, len(output), "VRFProof: output size = %d != %d", len(output), vrf.OutputSize)
   184  }
   185  
   186  func ping(sl *privval.SignerListenerEndpoint) {
   187  	msg := ocprivvalproto.Message{
   188  		Sum: &ocprivvalproto.Message_PingRequest{
   189  			PingRequest: &privvalproto.PingRequest{},
   190  		},
   191  	}
   192  	_, err := sl.SendRequest(msg)
   193  	if err != nil {
   194  		sl.Logger.Error("Benchmark::ping", "err", err)
   195  	}
   196  }