Skip to content

Commit 505a1e4

Browse files
Restrict ProposerVM P-chain height advancement (#3777)
Signed-off-by: Stephen Buttolph <stephen@avalabs.org> Co-authored-by: Arran Schlosberg <519948+ARR4N@users.noreply.github.com>
1 parent 478f5fd commit 505a1e4

File tree

4 files changed

+113
-6
lines changed

4 files changed

+113
-6
lines changed

vms/proposervm/block.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -193,7 +193,7 @@ func (p *postForkCommonComponents) buildChild(
193193

194194
// The child's P-Chain height is proposed as the optimal P-Chain height that
195195
// is at least the parent's P-Chain height
196-
pChainHeight, err := p.vm.optimalPChainHeight(ctx, parentPChainHeight)
196+
pChainHeight, err := p.vm.selectChildPChainHeight(ctx, parentPChainHeight)
197197
if err != nil {
198198
p.vm.ctx.Log.Error("unexpected build block failure",
199199
zap.String("reason", "failed to calculate optimal P-chain height"),

vms/proposervm/pre_fork_block.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -192,7 +192,7 @@ func (b *preForkBlock) buildChild(ctx context.Context) (Block, error) {
192192

193193
// The child's P-Chain height is proposed as the optimal P-Chain height that
194194
// is at least the minimum height
195-
pChainHeight, err := b.vm.optimalPChainHeight(ctx, b.vm.Upgrades.ApricotPhase4MinPChainHeight)
195+
pChainHeight, err := b.vm.selectChildPChainHeight(ctx, b.vm.Upgrades.ApricotPhase4MinPChainHeight)
196196
if err != nil {
197197
b.vm.ctx.Log.Error("unexpected build block failure",
198198
zap.String("reason", "failed to calculate optimal P-chain height"),

vms/proposervm/vm.go

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -725,13 +725,31 @@ func (vm *VM) notifyInnerBlockReady() {
725725
}
726726
}
727727

728-
func (vm *VM) optimalPChainHeight(ctx context.Context, minPChainHeight uint64) (uint64, error) {
729-
minimumHeight, err := vm.ctx.ValidatorState.GetMinimumHeight(ctx)
728+
// fujiOverridePChainHeightUntilHeight is the P-chain height at which the
729+
// proposervm will no longer attempt to keep the P-chain height the same.
730+
const fujiOverridePChainHeightUntilHeight = 200041
731+
732+
// fujiOverridePChainHeightUntilTimestamp is the timestamp at which the
733+
// proposervm will no longer attempt to keep the P-chain height the same.
734+
var fujiOverridePChainHeightUntilTimestamp = time.Date(2025, time.March, 7, 17, 0, 0, 0, time.UTC) // noon ET
735+
736+
func (vm *VM) selectChildPChainHeight(ctx context.Context, minPChainHeight uint64) (uint64, error) {
737+
var (
738+
now = vm.Clock.Time()
739+
shouldOverride = vm.ctx.NetworkID == constants.FujiID &&
740+
vm.ctx.SubnetID != constants.PrimaryNetworkID &&
741+
now.Before(fujiOverridePChainHeightUntilTimestamp) &&
742+
minPChainHeight < fujiOverridePChainHeightUntilHeight
743+
)
744+
if shouldOverride {
745+
return minPChainHeight, nil
746+
}
747+
748+
recommendedHeight, err := vm.ctx.ValidatorState.GetMinimumHeight(ctx)
730749
if err != nil {
731750
return 0, err
732751
}
733-
734-
return max(minimumHeight, minPChainHeight), nil
752+
return max(recommendedHeight, minPChainHeight), nil
735753
}
736754

737755
// parseInnerBlock attempts to parse the provided bytes as an inner block. If

vms/proposervm/vm_test.go

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ import (
3737
"github.com/ava-labs/avalanchego/upgrade"
3838
"github.com/ava-labs/avalanchego/upgrade/upgradetest"
3939
"github.com/ava-labs/avalanchego/utils"
40+
"github.com/ava-labs/avalanchego/utils/constants"
4041
"github.com/ava-labs/avalanchego/utils/logging"
4142
"github.com/ava-labs/avalanchego/utils/timer/mockable"
4243
"github.com/ava-labs/avalanchego/vms/proposervm/proposer"
@@ -2571,3 +2572,91 @@ func TestTimestampMetrics(t *testing.T) {
25712572
})
25722573
}
25732574
}
2575+
2576+
func TestSelectChildPChainHeight(t *testing.T) {
2577+
var (
2578+
activationTime = time.Unix(0, 0)
2579+
durangoTime = activationTime
2580+
2581+
beforeOverrideEnds = fujiOverridePChainHeightUntilTimestamp.Add(-time.Minute)
2582+
)
2583+
for _, test := range []struct {
2584+
name string
2585+
time time.Time
2586+
networkID uint32
2587+
subnetID ids.ID
2588+
currentPChainHeight uint64
2589+
minPChainHeight uint64
2590+
expectedPChainHeight uint64
2591+
}{
2592+
{
2593+
name: "no override - mainnet",
2594+
time: beforeOverrideEnds,
2595+
networkID: constants.MainnetID,
2596+
subnetID: ids.GenerateTestID(),
2597+
currentPChainHeight: fujiOverridePChainHeightUntilHeight + 2,
2598+
minPChainHeight: fujiOverridePChainHeightUntilHeight - 5,
2599+
expectedPChainHeight: fujiOverridePChainHeightUntilHeight + 2,
2600+
},
2601+
{
2602+
name: "no override - primary network",
2603+
time: beforeOverrideEnds,
2604+
networkID: constants.FujiID,
2605+
subnetID: constants.PrimaryNetworkID,
2606+
currentPChainHeight: fujiOverridePChainHeightUntilHeight + 2,
2607+
minPChainHeight: fujiOverridePChainHeightUntilHeight - 5,
2608+
expectedPChainHeight: fujiOverridePChainHeightUntilHeight + 2,
2609+
},
2610+
{
2611+
name: "no override - expired network",
2612+
time: fujiOverridePChainHeightUntilTimestamp,
2613+
networkID: constants.FujiID,
2614+
subnetID: ids.GenerateTestID(),
2615+
currentPChainHeight: fujiOverridePChainHeightUntilHeight + 2,
2616+
minPChainHeight: fujiOverridePChainHeightUntilHeight - 5,
2617+
expectedPChainHeight: fujiOverridePChainHeightUntilHeight + 2,
2618+
},
2619+
{
2620+
name: "no override - chain previously advanced",
2621+
time: beforeOverrideEnds,
2622+
networkID: constants.FujiID,
2623+
subnetID: ids.GenerateTestID(),
2624+
currentPChainHeight: fujiOverridePChainHeightUntilHeight + 2,
2625+
minPChainHeight: fujiOverridePChainHeightUntilHeight + 1,
2626+
expectedPChainHeight: fujiOverridePChainHeightUntilHeight + 2,
2627+
},
2628+
{
2629+
name: "override",
2630+
time: beforeOverrideEnds,
2631+
networkID: constants.FujiID,
2632+
subnetID: ids.GenerateTestID(),
2633+
currentPChainHeight: fujiOverridePChainHeightUntilHeight + 2,
2634+
minPChainHeight: fujiOverridePChainHeightUntilHeight - 5,
2635+
expectedPChainHeight: fujiOverridePChainHeightUntilHeight - 5,
2636+
},
2637+
} {
2638+
t.Run(test.name, func(t *testing.T) {
2639+
require := require.New(t)
2640+
2641+
_, vdrState, proVM, _ := initTestProposerVM(t, activationTime, durangoTime, 0)
2642+
defer func() {
2643+
require.NoError(proVM.Shutdown(context.Background()))
2644+
}()
2645+
2646+
proVM.Clock.Set(test.time)
2647+
proVM.ctx.NetworkID = test.networkID
2648+
proVM.ctx.SubnetID = test.subnetID
2649+
2650+
vdrState.GetMinimumHeightF = func(context.Context) (uint64, error) {
2651+
return test.currentPChainHeight, nil
2652+
}
2653+
2654+
actualPChainHeight, err := proVM.selectChildPChainHeight(
2655+
context.Background(),
2656+
test.minPChainHeight,
2657+
)
2658+
require.NoError(err)
2659+
require.Equal(test.expectedPChainHeight, actualPChainHeight)
2660+
})
2661+
}
2662+
}

0 commit comments

Comments
 (0)