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