github.com/devwanda/aphelion-staking@v0.33.9/privval/file_test.go (about) 1 package privval 2 3 import ( 4 "encoding/base64" 5 "fmt" 6 "io/ioutil" 7 "os" 8 "testing" 9 "time" 10 11 "github.com/stretchr/testify/assert" 12 "github.com/stretchr/testify/require" 13 14 "github.com/devwanda/aphelion-staking/crypto/ed25519" 15 "github.com/devwanda/aphelion-staking/types" 16 tmtime "github.com/devwanda/aphelion-staking/types/time" 17 ) 18 19 func TestGenLoadValidator(t *testing.T) { 20 assert := assert.New(t) 21 22 tempKeyFile, err := ioutil.TempFile("", "priv_validator_key_") 23 require.Nil(t, err) 24 tempStateFile, err := ioutil.TempFile("", "priv_validator_state_") 25 require.Nil(t, err) 26 27 privVal := GenFilePV(tempKeyFile.Name(), tempStateFile.Name()) 28 29 height := int64(100) 30 privVal.LastSignState.Height = height 31 privVal.Save() 32 addr := privVal.GetAddress() 33 34 privVal = LoadFilePV(tempKeyFile.Name(), tempStateFile.Name()) 35 assert.Equal(addr, privVal.GetAddress(), "expected privval addr to be the same") 36 assert.Equal(height, privVal.LastSignState.Height, "expected privval.LastHeight to have been saved") 37 } 38 39 func TestResetValidator(t *testing.T) { 40 tempKeyFile, err := ioutil.TempFile("", "priv_validator_key_") 41 require.Nil(t, err) 42 tempStateFile, err := ioutil.TempFile("", "priv_validator_state_") 43 require.Nil(t, err) 44 45 privVal := GenFilePV(tempKeyFile.Name(), tempStateFile.Name()) 46 emptyState := FilePVLastSignState{filePath: tempStateFile.Name()} 47 48 // new priv val has empty state 49 assert.Equal(t, privVal.LastSignState, emptyState) 50 51 // test vote 52 height, round := int64(10), 1 53 voteType := byte(types.PrevoteType) 54 blockID := types.BlockID{Hash: []byte{1, 2, 3}, PartsHeader: types.PartSetHeader{}} 55 vote := newVote(privVal.Key.Address, 0, height, round, voteType, blockID) 56 err = privVal.SignVote("mychainid", vote) 57 assert.NoError(t, err, "expected no error signing vote") 58 59 // priv val after signing is not same as empty 60 assert.NotEqual(t, privVal.LastSignState, emptyState) 61 62 // priv val after AcceptNewConnection is same as empty 63 privVal.Reset() 64 assert.Equal(t, privVal.LastSignState, emptyState) 65 } 66 67 func TestLoadOrGenValidator(t *testing.T) { 68 assert := assert.New(t) 69 70 tempKeyFile, err := ioutil.TempFile("", "priv_validator_key_") 71 require.Nil(t, err) 72 tempStateFile, err := ioutil.TempFile("", "priv_validator_state_") 73 require.Nil(t, err) 74 75 tempKeyFilePath := tempKeyFile.Name() 76 if err := os.Remove(tempKeyFilePath); err != nil { 77 t.Error(err) 78 } 79 tempStateFilePath := tempStateFile.Name() 80 if err := os.Remove(tempStateFilePath); err != nil { 81 t.Error(err) 82 } 83 84 privVal := LoadOrGenFilePV(tempKeyFilePath, tempStateFilePath) 85 addr := privVal.GetAddress() 86 privVal = LoadOrGenFilePV(tempKeyFilePath, tempStateFilePath) 87 assert.Equal(addr, privVal.GetAddress(), "expected privval addr to be the same") 88 } 89 90 func TestUnmarshalValidatorState(t *testing.T) { 91 assert, require := assert.New(t), require.New(t) 92 93 // create some fixed values 94 serialized := `{ 95 "height": "1", 96 "round": "1", 97 "step": 1 98 }` 99 100 val := FilePVLastSignState{} 101 err := cdc.UnmarshalJSON([]byte(serialized), &val) 102 require.Nil(err, "%+v", err) 103 104 // make sure the values match 105 assert.EqualValues(val.Height, 1) 106 assert.EqualValues(val.Round, 1) 107 assert.EqualValues(val.Step, 1) 108 109 // export it and make sure it is the same 110 out, err := cdc.MarshalJSON(val) 111 require.Nil(err, "%+v", err) 112 assert.JSONEq(serialized, string(out)) 113 } 114 115 func TestUnmarshalValidatorKey(t *testing.T) { 116 assert, require := assert.New(t), require.New(t) 117 118 // create some fixed values 119 privKey := ed25519.GenPrivKey() 120 pubKey := privKey.PubKey() 121 addr := pubKey.Address() 122 pubArray := [32]byte(pubKey.(ed25519.PubKeyEd25519)) 123 pubBytes := pubArray[:] 124 privArray := [64]byte(privKey) 125 privBytes := privArray[:] 126 pubB64 := base64.StdEncoding.EncodeToString(pubBytes) 127 privB64 := base64.StdEncoding.EncodeToString(privBytes) 128 129 serialized := fmt.Sprintf(`{ 130 "address": "%s", 131 "pub_key": { 132 "type": "tendermint/PubKeyEd25519", 133 "value": "%s" 134 }, 135 "priv_key": { 136 "type": "tendermint/PrivKeyEd25519", 137 "value": "%s" 138 } 139 }`, addr, pubB64, privB64) 140 141 val := FilePVKey{} 142 err := cdc.UnmarshalJSON([]byte(serialized), &val) 143 require.Nil(err, "%+v", err) 144 145 // make sure the values match 146 assert.EqualValues(addr, val.Address) 147 assert.EqualValues(pubKey, val.PubKey) 148 assert.EqualValues(privKey, val.PrivKey) 149 150 // export it and make sure it is the same 151 out, err := cdc.MarshalJSON(val) 152 require.Nil(err, "%+v", err) 153 assert.JSONEq(serialized, string(out)) 154 } 155 156 func TestSignVote(t *testing.T) { 157 assert := assert.New(t) 158 159 tempKeyFile, err := ioutil.TempFile("", "priv_validator_key_") 160 require.Nil(t, err) 161 tempStateFile, err := ioutil.TempFile("", "priv_validator_state_") 162 require.Nil(t, err) 163 164 privVal := GenFilePV(tempKeyFile.Name(), tempStateFile.Name()) 165 166 block1 := types.BlockID{Hash: []byte{1, 2, 3}, PartsHeader: types.PartSetHeader{}} 167 block2 := types.BlockID{Hash: []byte{3, 2, 1}, PartsHeader: types.PartSetHeader{}} 168 169 height, round := int64(10), 1 170 voteType := byte(types.PrevoteType) 171 172 // sign a vote for first time 173 vote := newVote(privVal.Key.Address, 0, height, round, voteType, block1) 174 err = privVal.SignVote("mychainid", vote) 175 assert.NoError(err, "expected no error signing vote") 176 177 // try to sign the same vote again; should be fine 178 err = privVal.SignVote("mychainid", vote) 179 assert.NoError(err, "expected no error on signing same vote") 180 181 // now try some bad votes 182 cases := []*types.Vote{ 183 newVote(privVal.Key.Address, 0, height, round-1, voteType, block1), // round regression 184 newVote(privVal.Key.Address, 0, height-1, round, voteType, block1), // height regression 185 newVote(privVal.Key.Address, 0, height-2, round+4, voteType, block1), // height regression and different round 186 newVote(privVal.Key.Address, 0, height, round, voteType, block2), // different block 187 } 188 189 for _, c := range cases { 190 err = privVal.SignVote("mychainid", c) 191 assert.Error(err, "expected error on signing conflicting vote") 192 } 193 194 // try signing a vote with a different time stamp 195 sig := vote.Signature 196 vote.Timestamp = vote.Timestamp.Add(time.Duration(1000)) 197 err = privVal.SignVote("mychainid", vote) 198 assert.NoError(err) 199 assert.Equal(sig, vote.Signature) 200 } 201 202 func TestSignProposal(t *testing.T) { 203 assert := assert.New(t) 204 205 tempKeyFile, err := ioutil.TempFile("", "priv_validator_key_") 206 require.Nil(t, err) 207 tempStateFile, err := ioutil.TempFile("", "priv_validator_state_") 208 require.Nil(t, err) 209 210 privVal := GenFilePV(tempKeyFile.Name(), tempStateFile.Name()) 211 212 block1 := types.BlockID{Hash: []byte{1, 2, 3}, PartsHeader: types.PartSetHeader{Total: 5, Hash: []byte{1, 2, 3}}} 213 block2 := types.BlockID{Hash: []byte{3, 2, 1}, PartsHeader: types.PartSetHeader{Total: 10, Hash: []byte{3, 2, 1}}} 214 height, round := int64(10), 1 215 216 // sign a proposal for first time 217 proposal := newProposal(height, round, block1) 218 err = privVal.SignProposal("mychainid", proposal) 219 assert.NoError(err, "expected no error signing proposal") 220 221 // try to sign the same proposal again; should be fine 222 err = privVal.SignProposal("mychainid", proposal) 223 assert.NoError(err, "expected no error on signing same proposal") 224 225 // now try some bad Proposals 226 cases := []*types.Proposal{ 227 newProposal(height, round-1, block1), // round regression 228 newProposal(height-1, round, block1), // height regression 229 newProposal(height-2, round+4, block1), // height regression and different round 230 newProposal(height, round, block2), // different block 231 } 232 233 for _, c := range cases { 234 err = privVal.SignProposal("mychainid", c) 235 assert.Error(err, "expected error on signing conflicting proposal") 236 } 237 238 // try signing a proposal with a different time stamp 239 sig := proposal.Signature 240 proposal.Timestamp = proposal.Timestamp.Add(time.Duration(1000)) 241 err = privVal.SignProposal("mychainid", proposal) 242 assert.NoError(err) 243 assert.Equal(sig, proposal.Signature) 244 } 245 246 func TestDifferByTimestamp(t *testing.T) { 247 tempKeyFile, err := ioutil.TempFile("", "priv_validator_key_") 248 require.Nil(t, err) 249 tempStateFile, err := ioutil.TempFile("", "priv_validator_state_") 250 require.Nil(t, err) 251 252 privVal := GenFilePV(tempKeyFile.Name(), tempStateFile.Name()) 253 254 block1 := types.BlockID{Hash: []byte{1, 2, 3}, PartsHeader: types.PartSetHeader{Total: 5, Hash: []byte{1, 2, 3}}} 255 height, round := int64(10), 1 256 chainID := "mychainid" 257 258 // test proposal 259 { 260 proposal := newProposal(height, round, block1) 261 err := privVal.SignProposal(chainID, proposal) 262 assert.NoError(t, err, "expected no error signing proposal") 263 signBytes := proposal.SignBytes(chainID) 264 sig := proposal.Signature 265 timeStamp := proposal.Timestamp 266 267 // manipulate the timestamp. should get changed back 268 proposal.Timestamp = proposal.Timestamp.Add(time.Millisecond) 269 var emptySig []byte 270 proposal.Signature = emptySig 271 err = privVal.SignProposal("mychainid", proposal) 272 assert.NoError(t, err, "expected no error on signing same proposal") 273 274 assert.Equal(t, timeStamp, proposal.Timestamp) 275 assert.Equal(t, signBytes, proposal.SignBytes(chainID)) 276 assert.Equal(t, sig, proposal.Signature) 277 } 278 279 // test vote 280 { 281 voteType := byte(types.PrevoteType) 282 blockID := types.BlockID{Hash: []byte{1, 2, 3}, PartsHeader: types.PartSetHeader{}} 283 vote := newVote(privVal.Key.Address, 0, height, round, voteType, blockID) 284 err := privVal.SignVote("mychainid", vote) 285 assert.NoError(t, err, "expected no error signing vote") 286 287 signBytes := vote.SignBytes(chainID) 288 sig := vote.Signature 289 timeStamp := vote.Timestamp 290 291 // manipulate the timestamp. should get changed back 292 vote.Timestamp = vote.Timestamp.Add(time.Millisecond) 293 var emptySig []byte 294 vote.Signature = emptySig 295 err = privVal.SignVote("mychainid", vote) 296 assert.NoError(t, err, "expected no error on signing same vote") 297 298 assert.Equal(t, timeStamp, vote.Timestamp) 299 assert.Equal(t, signBytes, vote.SignBytes(chainID)) 300 assert.Equal(t, sig, vote.Signature) 301 } 302 } 303 304 func newVote(addr types.Address, idx int, height int64, round int, typ byte, blockID types.BlockID) *types.Vote { 305 return &types.Vote{ 306 ValidatorAddress: addr, 307 ValidatorIndex: idx, 308 Height: height, 309 Round: round, 310 Type: types.SignedMsgType(typ), 311 Timestamp: tmtime.Now(), 312 BlockID: blockID, 313 } 314 } 315 316 func newProposal(height int64, round int, blockID types.BlockID) *types.Proposal { 317 return &types.Proposal{ 318 Height: height, 319 Round: round, 320 BlockID: blockID, 321 Timestamp: tmtime.Now(), 322 } 323 }