Skip to content

Commit 0d8581a

Browse files
Merge pull request #407 from ava-labs/delegation-cap
always enforce the delegation cap
2 parents e91784e + af503f0 commit 0d8581a

File tree

2 files changed

+277
-0
lines changed

2 files changed

+277
-0
lines changed

vms/platformvm/add_delegator_tx_test.go

Lines changed: 273 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -362,3 +362,276 @@ func TestAddDelegatorTxSemanticVerify(t *testing.T) {
362362
})
363363
}
364364
}
365+
366+
func TestAddDelegatorTxOverDelegatedRegression(t *testing.T) {
367+
vm, _ := defaultVM()
368+
vm.Ctx.Lock.Lock()
369+
defer func() {
370+
if err := vm.Shutdown(); err != nil {
371+
t.Fatal(err)
372+
}
373+
vm.Ctx.Lock.Unlock()
374+
}()
375+
376+
validatorStartTime := defaultGenesisTime.Add(syncBound).Add(1 * time.Second)
377+
validatorEndTime := validatorStartTime.Add(360 * 24 * time.Hour)
378+
key, err := vm.factory.NewPrivateKey()
379+
if err != nil {
380+
t.Fatal(err)
381+
}
382+
id := key.PublicKey().Address()
383+
384+
// create valid tx
385+
addValidatorTx, err := vm.newAddValidatorTx(
386+
vm.minValidatorStake,
387+
uint64(validatorStartTime.Unix()),
388+
uint64(validatorEndTime.Unix()),
389+
id,
390+
id,
391+
PercentDenominator,
392+
[]*crypto.PrivateKeySECP256K1R{keys[0]},
393+
ids.ShortEmpty, // change addr
394+
)
395+
if err != nil {
396+
t.Fatal(err)
397+
}
398+
399+
// trigger block creation
400+
if err := vm.mempool.IssueTx(addValidatorTx); err != nil {
401+
t.Fatal(err)
402+
}
403+
addValidatorBlockIntf, err := vm.BuildBlock()
404+
if err != nil {
405+
t.Fatal(err)
406+
}
407+
408+
// Verify the proposed block
409+
if err := addValidatorBlockIntf.Verify(); err != nil {
410+
t.Fatal(err)
411+
}
412+
413+
// Assert preferences are correct
414+
addValidatorBlock := addValidatorBlockIntf.(*ProposalBlock)
415+
options, err := addValidatorBlock.Options()
416+
if err != nil {
417+
t.Fatal(err)
418+
}
419+
420+
// verify the commit block
421+
commit := options[0].(*Commit)
422+
if err := commit.Verify(); err != nil {
423+
t.Fatal(err)
424+
}
425+
426+
// Accept the proposal block and the commit block
427+
if err := addValidatorBlock.Accept(); err != nil {
428+
t.Fatal(err)
429+
}
430+
if err := commit.Accept(); err != nil {
431+
t.Fatal(err)
432+
}
433+
434+
vm.clock.Set(validatorStartTime)
435+
436+
firstAdvanceTimeBlockIntf, err := vm.BuildBlock()
437+
if err != nil {
438+
t.Fatal(err)
439+
}
440+
441+
// Verify the proposed block
442+
if err := firstAdvanceTimeBlockIntf.Verify(); err != nil {
443+
t.Fatal(err)
444+
}
445+
446+
// Assert preferences are correct
447+
firstAdvanceTimeBlock := firstAdvanceTimeBlockIntf.(*ProposalBlock)
448+
options, err = firstAdvanceTimeBlock.Options()
449+
if err != nil {
450+
t.Fatal(err)
451+
}
452+
453+
// verify the commit block
454+
commit = options[0].(*Commit)
455+
if err := commit.Verify(); err != nil {
456+
t.Fatal(err)
457+
}
458+
459+
// Accept the proposal block and the commit block
460+
if err := firstAdvanceTimeBlock.Accept(); err != nil {
461+
t.Fatal(err)
462+
}
463+
if err := commit.Accept(); err != nil {
464+
t.Fatal(err)
465+
}
466+
467+
firstDelegatorStartTime := validatorStartTime.Add(syncBound).Add(1 * time.Second)
468+
firstDelegatorEndTime := firstDelegatorStartTime.Add(vm.minStakeDuration)
469+
470+
// create valid tx
471+
addFirstDelegatorTx, err := vm.newAddDelegatorTx(
472+
4*vm.minValidatorStake, // maximum amount of stake this delegator can provide
473+
uint64(firstDelegatorStartTime.Unix()),
474+
uint64(firstDelegatorEndTime.Unix()),
475+
id,
476+
keys[0].PublicKey().Address(),
477+
[]*crypto.PrivateKeySECP256K1R{keys[0], keys[1]},
478+
ids.ShortEmpty, // change addr
479+
)
480+
if err != nil {
481+
t.Fatal(err)
482+
}
483+
484+
// trigger block creation
485+
if err := vm.mempool.IssueTx(addFirstDelegatorTx); err != nil {
486+
t.Fatal(err)
487+
}
488+
addFirstDelegatorBlockIntf, err := vm.BuildBlock()
489+
if err != nil {
490+
t.Fatal(err)
491+
}
492+
493+
// Verify the proposed block
494+
if err := addFirstDelegatorBlockIntf.Verify(); err != nil {
495+
t.Fatal(err)
496+
}
497+
498+
// Assert preferences are correct
499+
addFirstDelegatorBlock := addFirstDelegatorBlockIntf.(*ProposalBlock)
500+
options, err = addFirstDelegatorBlock.Options()
501+
if err != nil {
502+
t.Fatal(err)
503+
}
504+
505+
// verify the commit block
506+
commit = options[0].(*Commit)
507+
if err := commit.Verify(); err != nil {
508+
t.Fatal(err)
509+
}
510+
511+
// Accept the proposal block and the commit block
512+
if err := addFirstDelegatorBlock.Accept(); err != nil {
513+
t.Fatal(err)
514+
}
515+
if err := commit.Accept(); err != nil {
516+
t.Fatal(err)
517+
}
518+
519+
vm.clock.Set(firstDelegatorStartTime)
520+
521+
secondAdvanceTimeBlockIntf, err := vm.BuildBlock()
522+
if err != nil {
523+
t.Fatal(err)
524+
}
525+
526+
// Verify the proposed block
527+
if err := secondAdvanceTimeBlockIntf.Verify(); err != nil {
528+
t.Fatal(err)
529+
}
530+
531+
// Assert preferences are correct
532+
secondAdvanceTimeBlock := secondAdvanceTimeBlockIntf.(*ProposalBlock)
533+
options, err = secondAdvanceTimeBlock.Options()
534+
if err != nil {
535+
t.Fatal(err)
536+
}
537+
538+
// verify the commit block
539+
commit = options[0].(*Commit)
540+
if err := commit.Verify(); err != nil {
541+
t.Fatal(err)
542+
}
543+
544+
// Accept the proposal block and the commit block
545+
if err := secondAdvanceTimeBlock.Accept(); err != nil {
546+
t.Fatal(err)
547+
}
548+
if err := commit.Accept(); err != nil {
549+
t.Fatal(err)
550+
}
551+
552+
secondDelegatorStartTime := firstDelegatorEndTime.Add(2 * time.Second)
553+
secondDelegatorEndTime := secondDelegatorStartTime.Add(vm.minStakeDuration)
554+
555+
vm.clock.Set(secondDelegatorStartTime.Add(-10 * syncBound))
556+
557+
// create valid tx
558+
addSecondDelegatorTx, err := vm.newAddDelegatorTx(
559+
vm.minDelegatorStake,
560+
uint64(secondDelegatorStartTime.Unix()),
561+
uint64(secondDelegatorEndTime.Unix()),
562+
id,
563+
keys[0].PublicKey().Address(),
564+
[]*crypto.PrivateKeySECP256K1R{keys[0], keys[1], keys[3]},
565+
ids.ShortEmpty, // change addr
566+
)
567+
if err != nil {
568+
t.Fatal(err)
569+
}
570+
571+
// trigger block creation
572+
if err := vm.mempool.IssueTx(addSecondDelegatorTx); err != nil {
573+
t.Fatal(err)
574+
}
575+
addSecondDelegatorBlockIntf, err := vm.BuildBlock()
576+
if err != nil {
577+
t.Fatal(err)
578+
}
579+
580+
// Verify the proposed block
581+
if err := addSecondDelegatorBlockIntf.Verify(); err != nil {
582+
t.Fatal(err)
583+
}
584+
585+
// Assert preferences are correct
586+
addSecondDelegatorBlock := addSecondDelegatorBlockIntf.(*ProposalBlock)
587+
options, err = addSecondDelegatorBlock.Options()
588+
if err != nil {
589+
t.Fatal(err)
590+
}
591+
592+
// verify the commit block
593+
commit = options[0].(*Commit)
594+
if err := commit.Verify(); err != nil {
595+
t.Fatal(err)
596+
}
597+
598+
// Accept the proposal block and the commit block
599+
if err := addSecondDelegatorBlock.Accept(); err != nil {
600+
t.Fatal(err)
601+
}
602+
if err := commit.Accept(); err != nil {
603+
t.Fatal(err)
604+
}
605+
606+
thirdDelegatorStartTime := firstDelegatorEndTime.Add(-time.Second)
607+
thirdDelegatorEndTime := thirdDelegatorStartTime.Add(vm.minStakeDuration)
608+
609+
// create valid tx
610+
addThirdDelegatorTx, err := vm.newAddDelegatorTx(
611+
vm.minDelegatorStake,
612+
uint64(thirdDelegatorStartTime.Unix()),
613+
uint64(thirdDelegatorEndTime.Unix()),
614+
id,
615+
keys[0].PublicKey().Address(),
616+
[]*crypto.PrivateKeySECP256K1R{keys[0], keys[1], keys[4]},
617+
ids.ShortEmpty, // change addr
618+
)
619+
if err != nil {
620+
t.Fatal(err)
621+
}
622+
623+
// trigger block creation
624+
if err := vm.mempool.IssueTx(addThirdDelegatorTx); err != nil {
625+
t.Fatal(err)
626+
}
627+
628+
addThirdDelegatorBlockIntf, err := vm.BuildBlock()
629+
if err != nil {
630+
t.Fatal(err)
631+
}
632+
633+
// Verify the proposed block is invalid
634+
if err := addThirdDelegatorBlockIntf.Verify(); err == nil {
635+
t.Fatalf("should have marked the delegator as being over delegated")
636+
}
637+
}

vms/platformvm/vm.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1343,6 +1343,10 @@ func (vm *VM) maxStakeAmount(db database.Database, subnetID ids.ID, nodeID ids.S
13431343
toRemove := toRemoveHeap[0]
13441344
toRemoveHeap = toRemoveHeap[1:]
13451345

1346+
if currentWeight > maxWeight && !startTime.After(toRemove.EndTime()) {
1347+
maxWeight = currentWeight
1348+
}
1349+
13461350
newWeight, err := safemath.Sub64(currentWeight, toRemove.Wght)
13471351
if err != nil {
13481352
return 0, err

0 commit comments

Comments
 (0)