Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merge unlocked stake outputs #3231

Merged
merged 12 commits into from
Jul 26, 2024
32 changes: 19 additions & 13 deletions wallet/chain/p/builder/builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -1052,6 +1052,22 @@ func (b *builder) spend(
}
}

for assetID, amount := range amountsToStake {
if amount == 0 {
continue
}

stakeOutputs = append(stakeOutputs, &avax.TransferableOutput{
Asset: avax.Asset{
ID: assetID,
},
Out: &secp256k1fx.TransferOutput{
Amt: amount,
OutputOwners: *changeOwner,
},
})
}

// Iterate over the unlocked UTXOs
for _, utxo := range utxos {
assetID := utxo.AssetID()
Expand Down Expand Up @@ -1103,24 +1119,14 @@ func (b *builder) spend(
)
amountsToBurn[assetID] -= amountToBurn

amountAvalibleToStake := out.Amt - amountToBurn
amountAvailableToStake := out.Amt - amountToBurn
Copy link
Contributor Author

@StephenButtolph StephenButtolph Jul 24, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

typo fix (got in before the sybils!)

// Burn any value that should be burned
amountToStake := min(
remainingAmountToStake, // Amount we still need to stake
amountAvalibleToStake, // Amount available to stake
amountAvailableToStake, // Amount available to stake
)
amountsToStake[assetID] -= amountToStake
if amountToStake > 0 {
// Some of this input was put for staking
stakeOutputs = append(stakeOutputs, &avax.TransferableOutput{
Asset: utxo.Asset,
Out: &secp256k1fx.TransferOutput{
Amt: amountToStake,
OutputOwners: *changeOwner,
},
})
}
if remainingAmount := amountAvalibleToStake - amountToStake; remainingAmount > 0 {
if remainingAmount := amountAvailableToStake - amountToStake; remainingAmount > 0 {
// This input had extra value, so some of it must be returned
changeOutputs = append(changeOutputs, &avax.TransferableOutput{
Asset: utxo.Asset,
Expand Down
36 changes: 34 additions & 2 deletions wallet/chain/p/builder_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -544,8 +544,35 @@ func TestAddPermissionlessValidatorTx(t *testing.T) {
require = require.New(t)

// backend
utxosKey = testKeys[1]
utxos = makeTestUTXOs(utxosKey)
utxosOffset uint64 = 2024
utxosKey = testKeys[1]
utxosAddr = utxosKey.Address()
)
makeUTXO := func(amount uint64) *avax.UTXO {
utxosOffset++
return &avax.UTXO{
UTXOID: avax.UTXOID{
TxID: ids.Empty.Prefix(utxosOffset),
OutputIndex: uint32(utxosOffset),
},
Asset: avax.Asset{ID: avaxAssetID},
Out: &secp256k1fx.TransferOutput{
Amt: amount,
OutputOwners: secp256k1fx.OutputOwners{
Locktime: 0,
Addrs: []ids.ShortID{utxosAddr},
Threshold: 1,
},
},
}
}

var (
utxos = []*avax.UTXO{
makeUTXO(testContext.AddPrimaryNetworkValidatorFee), // UTXO to pay the fee
makeUTXO(1 * units.NanoAvax), // small UTXO
makeUTXO(9 * units.Avax), // large UTXO
}
chainUTXOs = common.NewDeterministicChainUTXOs(require, map[ids.ID][]*avax.UTXO{
constants.PlatformChainID: utxos,
})
Expand Down Expand Up @@ -611,6 +638,11 @@ func TestAddPermissionlessValidatorTx(t *testing.T) {
),
addInputAmounts(utx.Ins),
)

// Outputs should be merged if possible. For example, if there are two
// unlocked inputs consumed for staking, this should only produce one staked
// output.
require.Len(utx.StakeOuts, 1)
}

func TestAddPermissionlessDelegatorTx(t *testing.T) {
Expand Down
Loading