mirror of https://github.com/poanetwork/gecko.git
241 lines
6.3 KiB
Go
241 lines
6.3 KiB
Go
// (c) 2019-2020, Ava Labs, Inc. All rights reserved.
|
|
// See the file LICENSE for licensing terms.
|
|
|
|
package platformvm
|
|
|
|
import (
|
|
"testing"
|
|
"time"
|
|
)
|
|
|
|
func TestAdvanceTimeTxSyntacticVerify(t *testing.T) {
|
|
// Case 1: Tx is nil
|
|
var tx *advanceTimeTx
|
|
if err := tx.SyntacticVerify(); err == nil {
|
|
t.Fatal("should have failed verification because tx is nil")
|
|
}
|
|
|
|
// Case 2: Timestamp is ahead of synchrony bound
|
|
vm := defaultVM()
|
|
tx = &advanceTimeTx{
|
|
Time: uint64(defaultGenesisTime.Add(Delta).Add(1 * time.Second).Unix()),
|
|
vm: vm,
|
|
}
|
|
|
|
err := tx.SyntacticVerify()
|
|
if err == nil {
|
|
t.Fatal("should've failed verification because timestamp is ahead of synchrony bound")
|
|
}
|
|
|
|
// Case 3: Valid
|
|
tx.Time = uint64(defaultGenesisTime.Add(Delta).Unix())
|
|
err = tx.SyntacticVerify()
|
|
if err != nil {
|
|
t.Fatalf("should've passed verification but got: %v", err)
|
|
}
|
|
}
|
|
|
|
// Ensure semantic verification fails when proposed timestamp is at or before current timestamp
|
|
func TestAdvanceTimeTxTimestampTooEarly(t *testing.T) {
|
|
vm := defaultVM()
|
|
|
|
tx := &advanceTimeTx{
|
|
Time: uint64(defaultGenesisTime.Unix()),
|
|
vm: vm,
|
|
}
|
|
_, _, _, _, err := tx.SemanticVerify(vm.DB)
|
|
if err == nil {
|
|
t.Fatal("should've failed verification because proposed timestamp same as current timestamp")
|
|
}
|
|
}
|
|
|
|
// Ensure semantic verification fails when proposed timestamp is after next validator set change time
|
|
func TestAdvanceTimeTxTimestampTooLate(t *testing.T) {
|
|
vm := defaultVM()
|
|
|
|
// Case 1: Timestamp is after next validator start time
|
|
// Add a pending validator
|
|
pendingValidatorStartTime := defaultGenesisTime.Add(1 * time.Second)
|
|
pendingValidatorEndTime := pendingValidatorStartTime.Add(MinimumStakingDuration)
|
|
nodeIDKey, _ := vm.factory.NewPrivateKey()
|
|
nodeID := nodeIDKey.PublicKey().Address()
|
|
addPendingValidatorTx, err := vm.newAddDefaultSubnetValidatorTx(
|
|
defaultNonce+1,
|
|
defaultStakeAmount,
|
|
uint64(pendingValidatorStartTime.Unix()),
|
|
uint64(pendingValidatorEndTime.Unix()),
|
|
nodeID,
|
|
nodeID,
|
|
NumberOfShares,
|
|
testNetworkID,
|
|
defaultKey,
|
|
)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
err = vm.putPendingValidators(
|
|
vm.DB,
|
|
&EventHeap{
|
|
SortByStartTime: true,
|
|
Txs: []TimedTx{addPendingValidatorTx},
|
|
},
|
|
DefaultSubnetID,
|
|
)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
tx := &advanceTimeTx{
|
|
Time: uint64(pendingValidatorStartTime.Add(1 * time.Second).Unix()),
|
|
vm: vm,
|
|
}
|
|
_, _, _, _, err = tx.SemanticVerify(vm.DB)
|
|
if err == nil {
|
|
t.Fatal("should've failed verification because proposed timestamp is after pending validator start time")
|
|
}
|
|
|
|
// Case 2: Timestamp is after next validator end time
|
|
vm = defaultVM()
|
|
|
|
// fast forward clock to 10 seconds before genesis validators stop validating
|
|
vm.clock.Set(defaultValidateEndTime.Add(-10 * time.Second))
|
|
|
|
// Proposes advancing timestamp to 1 second after genesis validators stop validating
|
|
tx = &advanceTimeTx{
|
|
Time: uint64(defaultValidateEndTime.Add(1 * time.Second).Unix()),
|
|
vm: vm,
|
|
}
|
|
|
|
_, _, _, _, err = tx.SemanticVerify(vm.DB)
|
|
t.Log(err)
|
|
if err == nil {
|
|
t.Fatal("should've failed verification because proposed timestamp is after pending validator start time")
|
|
}
|
|
}
|
|
|
|
// Ensure semantic verification updates the current and pending validator sets correctly
|
|
func TestAdvanceTimeTxUpdateValidators(t *testing.T) {
|
|
vm := defaultVM()
|
|
|
|
// Case 1: Timestamp is after next validator start time
|
|
// Add a pending validator
|
|
pendingValidatorStartTime := defaultGenesisTime.Add(1 * time.Second)
|
|
pendingValidatorEndTime := pendingValidatorStartTime.Add(MinimumStakingDuration)
|
|
nodeIDKey, _ := vm.factory.NewPrivateKey()
|
|
nodeID := nodeIDKey.PublicKey().Address()
|
|
addPendingValidatorTx, err := vm.newAddDefaultSubnetValidatorTx(
|
|
defaultNonce+1,
|
|
defaultStakeAmount,
|
|
uint64(pendingValidatorStartTime.Unix()),
|
|
uint64(pendingValidatorEndTime.Unix()),
|
|
nodeID,
|
|
nodeID,
|
|
NumberOfShares,
|
|
testNetworkID,
|
|
defaultKey,
|
|
)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
err = vm.putPendingValidators(
|
|
vm.DB,
|
|
&EventHeap{
|
|
SortByStartTime: true,
|
|
Txs: []TimedTx{addPendingValidatorTx},
|
|
},
|
|
DefaultSubnetID,
|
|
)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
tx := &advanceTimeTx{
|
|
Time: uint64(pendingValidatorStartTime.Unix()),
|
|
vm: vm,
|
|
}
|
|
onCommit, onAbort, _, _, err := tx.SemanticVerify(vm.DB)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
onCommitCurrentEvents, err := vm.getCurrentValidators(onCommit, DefaultSubnetID)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if onCommitCurrentEvents.Len() != len(keys)+1 { // Each key in [keys] is a validator to start with...then we added a validator
|
|
t.Fatalf("Should have added the validator to the validator set")
|
|
}
|
|
|
|
onCommitPendingEvents, err := vm.getPendingValidators(onCommit, DefaultSubnetID)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if onCommitPendingEvents.Len() != 0 {
|
|
t.Fatalf("Should have removed the validator from the pending validator set")
|
|
}
|
|
|
|
onAbortCurrentEvents, err := vm.getCurrentValidators(onAbort, DefaultSubnetID)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if onAbortCurrentEvents.Len() != len(keys) {
|
|
t.Fatalf("Shouldn't have added the validator to the validator set")
|
|
}
|
|
|
|
onAbortPendingEvents, err := vm.getPendingValidators(onAbort, DefaultSubnetID)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if onAbortPendingEvents.Len() != 1 {
|
|
t.Fatalf("Shouldn't have removed the validator from the pending validator set")
|
|
}
|
|
}
|
|
|
|
// Test method InitiallyPrefersCommit
|
|
func TestAdvanceTimeTxInitiallyPrefersCommit(t *testing.T) {
|
|
vm := defaultVM()
|
|
|
|
// Proposed advancing timestamp to 1 second after current timestamp
|
|
tx, err := vm.newAdvanceTimeTx(defaultGenesisTime.Add(1 * time.Second))
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
if tx.InitiallyPrefersCommit() {
|
|
t.Fatal("should not prefer to commit this tx because its proposed timestamp is after wall clock time")
|
|
}
|
|
|
|
// advance wall clock time
|
|
vm.clock.Set(defaultGenesisTime.Add(2 * time.Second))
|
|
if !tx.InitiallyPrefersCommit() {
|
|
t.Fatal("should prefer to commit this tx because its proposed timestamp is before wall clock time")
|
|
}
|
|
}
|
|
|
|
// Ensure marshaling/unmarshaling works
|
|
func TestAdvanceTimeTxUnmarshal(t *testing.T) {
|
|
vm := defaultVM()
|
|
|
|
tx, err := vm.newAdvanceTimeTx(defaultGenesisTime)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
bytes, err := Codec.Marshal(tx)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
var unmarshaledTx advanceTimeTx
|
|
err = Codec.Unmarshal(bytes, &unmarshaledTx)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
if tx.Time != unmarshaledTx.Time {
|
|
t.Fatal("should have same timestamp")
|
|
}
|
|
}
|