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 }