Skip to content

Commit

Permalink
Merge branch 'implement-acp-77-warp-signing' into implement-acp-77-in…
Browse files Browse the repository at this point in the history
…crease-balance-tx
  • Loading branch information
StephenButtolph authored Oct 14, 2024
2 parents a49b877 + e61c8f7 commit 9bf4d58
Show file tree
Hide file tree
Showing 17 changed files with 127 additions and 68 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/build-macos-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ jobs:
# This workflow contains a single job called "build"
build-mac:
# The type of runner that the job will run on
runs-on: macos-12
runs-on: macos-14
permissions:
id-token: write
contents: read
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ jobs:
strategy:
fail-fast: false
matrix:
os: [macos-12, ubuntu-20.04, ubuntu-22.04, ubuntu-24.04, windows-2022, custom-arm64-jammy, custom-arm64-noble]
os: [macos-14, ubuntu-20.04, ubuntu-22.04, ubuntu-24.04, windows-2022, custom-arm64-jammy, custom-arm64-noble]
steps:
- uses: actions/checkout@v4
- uses: ./.github/actions/setup-go-for-project
Expand Down
2 changes: 1 addition & 1 deletion config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -793,8 +793,8 @@ func getTxFeeConfig(v *viper.Viper, networkID uint32) genesis.TxFeeConfig {
MinPrice: gas.Price(v.GetUint64(DynamicFeesMinGasPriceKey)),
ExcessConversionConstant: gas.Gas(v.GetUint64(DynamicFeesExcessConversionConstantKey)),
},
ValidatorFeeCapacity: gas.Gas(v.GetUint64(ValidatorFeesCapacityKey)),
ValidatorFeeConfig: validatorfee.Config{
Capacity: gas.Gas(v.GetUint64(ValidatorFeesCapacityKey)),
Target: gas.Gas(v.GetUint64(ValidatorFeesTargetKey)),
MinPrice: gas.Price(v.GetUint64(ValidatorFeesMinPriceKey)),
ExcessConversionConstant: gas.Gas(v.GetUint64(ValidatorFeesExcessConversionConstantKey)),
Expand Down
2 changes: 1 addition & 1 deletion config/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ func addNodeFlags(fs *pflag.FlagSet) {

// AVAX fees:
// Validator fees:
fs.Uint64(ValidatorFeesCapacityKey, uint64(genesis.LocalParams.ValidatorFeeCapacity), "Maximum number of validators")
fs.Uint64(ValidatorFeesCapacityKey, uint64(genesis.LocalParams.ValidatorFeeConfig.Capacity), "Maximum number of validators")
fs.Uint64(ValidatorFeesTargetKey, uint64(genesis.LocalParams.ValidatorFeeConfig.Target), "Target number of validators")
fs.Uint64(ValidatorFeesMinPriceKey, uint64(genesis.LocalParams.ValidatorFeeConfig.MinPrice), "Minimum validator price in nAVAX per second")
fs.Uint64(ValidatorFeesExcessConversionConstantKey, uint64(genesis.LocalParams.ValidatorFeeConfig.ExcessConversionConstant), "Constant to convert validator excess price")
Expand Down
2 changes: 1 addition & 1 deletion genesis/genesis_fuji.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,8 @@ var (
// hardcode the result.
ExcessConversionConstant: 5_410_106, // Double every 30s
},
ValidatorFeeCapacity: 20_000,
ValidatorFeeConfig: validatorfee.Config{
Capacity: 20_000,
Target: 10_000,
MinPrice: gas.Price(512 * units.NanoAvax),
// ExcessConversionConstant = (Capacity - Target) * NumberOfSecondsPerDoubling / ln(2)
Expand Down
2 changes: 1 addition & 1 deletion genesis/genesis_local.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,8 +70,8 @@ var (
// hardcode the result.
ExcessConversionConstant: 5_410_106, // Double every 30s
},
ValidatorFeeCapacity: 20_000,
ValidatorFeeConfig: validatorfee.Config{
Capacity: 20_000,
Target: 10_000,
MinPrice: gas.Price(1 * units.NanoAvax),
// ExcessConversionConstant = (Capacity - Target) * NumberOfSecondsPerDoubling / ln(2)
Expand Down
2 changes: 1 addition & 1 deletion genesis/genesis_mainnet.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,8 @@ var (
// hardcode the result.
ExcessConversionConstant: 5_410_106, // Double every 30s
},
ValidatorFeeCapacity: 20_000,
ValidatorFeeConfig: validatorfee.Config{
Capacity: 20_000,
Target: 10_000,
MinPrice: gas.Price(512 * units.NanoAvax),
// ExcessConversionConstant = (Capacity - Target) * NumberOfSecondsPerDoubling / ln(2)
Expand Down
9 changes: 4 additions & 5 deletions genesis/params.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,10 @@ type StakingConfig struct {
}

type TxFeeConfig struct {
CreateAssetTxFee uint64 `json:"createAssetTxFee"`
StaticFeeConfig txfee.StaticConfig `json:"staticFeeConfig"`
DynamicFeeConfig gas.Config `json:"dynamicFeeConfig"`
ValidatorFeeCapacity gas.Gas `json:"validatorFeeCapacity"`
ValidatorFeeConfig validatorfee.Config `json:"validatorFeeConfig"`
CreateAssetTxFee uint64 `json:"createAssetTxFee"`
StaticFeeConfig txfee.StaticConfig `json:"staticFeeConfig"`
DynamicFeeConfig gas.Config `json:"dynamicFeeConfig"`
ValidatorFeeConfig validatorfee.Config `json:"validatorFeeConfig"`
}

type Params struct {
Expand Down
23 changes: 23 additions & 0 deletions network/p2p/acp118/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (

"google.golang.org/protobuf/proto"

"github.com/ava-labs/avalanchego/cache"
"github.com/ava-labs/avalanchego/ids"
"github.com/ava-labs/avalanchego/network/p2p"
"github.com/ava-labs/avalanchego/proto/pb/sdk"
Expand All @@ -32,7 +33,22 @@ type Verifier interface {

// NewHandler returns an instance of Handler
func NewHandler(verifier Verifier, signer warp.Signer) *Handler {
return NewCachedHandler(
&cache.Empty[ids.ID, []byte]{},
verifier,
signer,
)
}

// NewCachedHandler returns an instance of Handler that caches successful
// requests.
func NewCachedHandler(
cacher cache.Cacher[ids.ID, []byte],
verifier Verifier,
signer warp.Signer,
) *Handler {
return &Handler{
cacher: cacher,
verifier: verifier,
signer: signer,
}
Expand All @@ -42,6 +58,7 @@ func NewHandler(verifier Verifier, signer warp.Signer) *Handler {
type Handler struct {
p2p.NoOpHandler

cacher cache.Cacher[ids.ID, []byte]
verifier Verifier
signer warp.Signer
}
Expand All @@ -68,6 +85,11 @@ func (h *Handler) AppRequest(
}
}

msgID := msg.ID()
if responseBytes, ok := h.cacher.Get(msgID); ok {
return responseBytes, nil
}

if err := h.verifier.Verify(ctx, msg, request.Justification); err != nil {
return nil, err
}
Expand All @@ -92,5 +114,6 @@ func (h *Handler) AppRequest(
}
}

h.cacher.Put(msgID, responseBytes)
return responseBytes, nil
}
79 changes: 59 additions & 20 deletions network/p2p/acp118/handler_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"github.com/stretchr/testify/require"
"google.golang.org/protobuf/proto"

"github.com/ava-labs/avalanchego/cache"
"github.com/ava-labs/avalanchego/ids"
"github.com/ava-labs/avalanchego/network/p2p/p2ptest"
"github.com/ava-labs/avalanchego/proto/pb/sdk"
Expand All @@ -23,20 +24,46 @@ var _ Verifier = (*testVerifier)(nil)

func TestHandler(t *testing.T) {
tests := []struct {
name string
verifier Verifier
expectedErr error
expectedVerify bool
name string
cacher cache.Cacher[ids.ID, []byte]
verifier Verifier
expectedErrs []error
}{
{
name: "signature fails verification",
verifier: &testVerifier{Err: &common.AppError{Code: 123}},
expectedErr: &common.AppError{Code: 123},
name: "signature fails verification",
cacher: &cache.Empty[ids.ID, []byte]{},
verifier: &testVerifier{
Errs: []*common.AppError{
{Code: 123},
},
},
expectedErrs: []error{
&common.AppError{Code: 123},
},
},
{
name: "signature signed",
verifier: &testVerifier{},
expectedVerify: true,
name: "signature signed",
cacher: &cache.Empty[ids.ID, []byte]{},
verifier: &testVerifier{},
expectedErrs: []error{
nil,
},
},
{
name: "signature is cached",
cacher: &cache.LRU[ids.ID, []byte]{
Size: 1,
},
verifier: &testVerifier{
Errs: []*common.AppError{
nil,
{Code: 123}, // The valid response should be cached
},
},
expectedErrs: []error{
nil,
nil,
},
},
}

Expand All @@ -51,7 +78,7 @@ func TestHandler(t *testing.T) {
networkID := uint32(123)
chainID := ids.GenerateTestID()
signer := warp.NewSigner(sk, networkID, chainID)
h := NewHandler(tt.verifier, signer)
h := NewCachedHandler(tt.cacher, tt.verifier, signer)
clientNodeID := ids.GenerateTestNodeID()
serverNodeID := ids.GenerateTestNodeID()
c := p2ptest.NewClient(
Expand All @@ -77,12 +104,17 @@ func TestHandler(t *testing.T) {
requestBytes, err := proto.Marshal(request)
require.NoError(err)

done := make(chan struct{})
var (
expectedErr error
handled = make(chan struct{})
)
onResponse := func(_ context.Context, _ ids.NodeID, responseBytes []byte, appErr error) {
defer close(done)
defer func() {
handled <- struct{}{}
}()

require.ErrorIs(appErr, expectedErr)
if appErr != nil {
require.ErrorIs(tt.expectedErr, appErr)
return
}

Expand All @@ -92,24 +124,31 @@ func TestHandler(t *testing.T) {
signature, err := bls.SignatureFromBytes(response.Signature)
require.NoError(err)

require.Equal(tt.expectedVerify, bls.Verify(pk, signature, request.Message))
require.True(bls.Verify(pk, signature, request.Message))
}

require.NoError(c.AppRequest(ctx, set.Of(clientNodeID), requestBytes, onResponse))
<-done
for _, expectedErr = range tt.expectedErrs {
require.NoError(c.AppRequest(ctx, set.Of(clientNodeID), requestBytes, onResponse))
<-handled
}
})
}
}

// The zero value of testVerifier allows signing
type testVerifier struct {
Err *common.AppError
Errs []*common.AppError
}

func (t testVerifier) Verify(
func (t *testVerifier) Verify(
context.Context,
*warp.UnsignedMessage,
[]byte,
) *common.AppError {
return t.Err
if len(t.Errs) == 0 {
return nil
}
err := t.Errs[0]
t.Errs = t.Errs[1:]
return err
}
25 changes: 8 additions & 17 deletions network/p2p/router.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,6 @@ type pendingAppRequest struct {
callback AppResponseCallback
}

// meteredHandler emits metrics for a Handler
type meteredHandler struct {
*responder
metrics
}

type metrics struct {
msgTime *prometheus.GaugeVec
msgCount *prometheus.CounterVec
Expand Down Expand Up @@ -69,7 +63,7 @@ type router struct {
metrics metrics

lock sync.RWMutex
handlers map[uint64]*meteredHandler
handlers map[uint64]*responder
pendingAppRequests map[uint32]pendingAppRequest
requestID uint32
}
Expand All @@ -84,7 +78,7 @@ func newRouter(
log: log,
sender: sender,
metrics: metrics,
handlers: make(map[uint64]*meteredHandler),
handlers: make(map[uint64]*responder),
pendingAppRequests: make(map[uint32]pendingAppRequest),
// invariant: sdk uses odd-numbered requestIDs
requestID: 1,
Expand All @@ -99,14 +93,11 @@ func (r *router) addHandler(handlerID uint64, handler Handler) error {
return fmt.Errorf("failed to register handler id %d: %w", handlerID, ErrExistingAppProtocol)
}

r.handlers[handlerID] = &meteredHandler{
responder: &responder{
Handler: handler,
handlerID: handlerID,
log: r.log,
sender: r.sender,
},
metrics: r.metrics,
r.handlers[handlerID] = &responder{
Handler: handler,
handlerID: handlerID,
log: r.log,
sender: r.sender,
}

return nil
Expand Down Expand Up @@ -235,7 +226,7 @@ func (r *router) AppGossip(ctx context.Context, nodeID ids.NodeID, gossip []byte
// - A boolean indicating that parsing succeeded.
//
// Invariant: Assumes [r.lock] isn't held.
func (r *router) parse(prefixedMsg []byte) ([]byte, *meteredHandler, string, bool) {
func (r *router) parse(prefixedMsg []byte) ([]byte, *responder, string, bool) {
handlerID, msg, ok := ParseMessage(prefixedMsg)
if !ok {
return nil, nil, "", false
Expand Down
1 change: 0 additions & 1 deletion node/node.go
Original file line number Diff line number Diff line change
Expand Up @@ -1217,7 +1217,6 @@ func (n *Node) initVMs() error {
CreateAssetTxFee: n.Config.CreateAssetTxFee,
StaticFeeConfig: n.Config.StaticFeeConfig,
DynamicFeeConfig: n.Config.DynamicFeeConfig,
ValidatorFeeCapacity: n.Config.ValidatorFeeCapacity,
ValidatorFeeConfig: n.Config.ValidatorFeeConfig,
UptimePercentage: n.Config.UptimeRequirement,
MinValidatorStake: n.Config.MinValidatorStake,
Expand Down
7 changes: 5 additions & 2 deletions tests/fixture/bootstrapmonitor/e2e/e2e_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -234,15 +234,18 @@ func buildImage(tc tests.TestContext, imageName string, forceNewHash bool, scrip
repoRoot, err := e2e.GetRepoRootPath(repoRelativePath)
require.NoError(err)

var args []string
args := []string{
"-x", // Ensure script output to aid in debugging
filepath.Join(repoRoot, "scripts", scriptName),
}
if forceNewHash {
// Ensure the build results in a new image hash by preventing use of a cached final stage
args = append(args, "--no-cache-filter", "execution")
}

cmd := exec.CommandContext(
tc.DefaultContext(),
filepath.Join(repoRoot, "scripts", scriptName),
"bash",
args...,
) // #nosec G204
cmd.Env = append(os.Environ(),
Expand Down
3 changes: 1 addition & 2 deletions vms/platformvm/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,7 @@ type Config struct {
DynamicFeeConfig gas.Config

// ACP-77 validator fees are active after Etna
ValidatorFeeCapacity gas.Gas
ValidatorFeeConfig validatorfee.Config
ValidatorFeeConfig validatorfee.Config

// Provides access to the uptime manager as a thread safe data structure
UptimeLockedCalculator uptime.LockedCalculator
Expand Down
4 changes: 2 additions & 2 deletions vms/platformvm/txs/executor/standard_tx_executor.go
Original file line number Diff line number Diff line change
Expand Up @@ -586,7 +586,7 @@ func (e *StandardTxExecutor) ConvertSubnetTx(tx *txs.ConvertSubnetTx) error {
}
if vdr.Balance != 0 {
// We are attempting to add an active validator
if gas.Gas(e.State.NumActiveSubnetOnlyValidators()) >= e.Backend.Config.ValidatorFeeCapacity {
if gas.Gas(e.State.NumActiveSubnetOnlyValidators()) >= e.Backend.Config.ValidatorFeeConfig.Capacity {
return errMaxNumActiveValidators
}

Expand Down Expand Up @@ -772,7 +772,7 @@ func (e *StandardTxExecutor) RegisterSubnetValidatorTx(tx *txs.RegisterSubnetVal
}
if tx.Balance != 0 {
// We are attempting to add an active validator
if gas.Gas(e.State.NumActiveSubnetOnlyValidators()) >= e.Backend.Config.ValidatorFeeCapacity {
if gas.Gas(e.State.NumActiveSubnetOnlyValidators()) >= e.Backend.Config.ValidatorFeeConfig.Capacity {
return errMaxNumActiveValidators
}

Expand Down
Loading

0 comments on commit 9bf4d58

Please sign in to comment.