wallet-core: compute residual amount for recoup properly

This commit is contained in:
Florian Dold 2022-11-02 13:40:03 +01:00
parent 87bc4a6fcd
commit fe011321a4
No known key found for this signature in database
GPG Key ID: D2E4F00F29D02A4B
7 changed files with 30 additions and 9 deletions

View File

@ -534,6 +534,8 @@ export interface BackupRefreshCoinSource {
* Public key of the coin that was refreshed into this coin.
*/
old_coin_pub: string;
refresh_group_id: string;
}
/**

View File

@ -181,6 +181,7 @@ export async function runRevocationTest(t: GlobalTestState) {
await makeTestPayment(t, { wallet, merchant, order });
wallet.deleteDatabase();
await withdrawViaBank(t, { wallet, bank, exchange, amount: "TESTKUDOS:15" });
const coinDump = await wallet.client.call(WalletApiOperation.DumpCoins, {});

View File

@ -640,6 +640,7 @@ export interface WithdrawCoinSource {
export interface RefreshCoinSource {
type: CoinSourceType.Refresh;
refreshGroupId: string;
oldCoinPub: string;
}

View File

@ -240,6 +240,7 @@ export async function exportBackup(
bcs = {
type: BackupCoinSourceType.Refresh,
old_coin_pub: coin.coinSource.oldCoinPub,
refresh_group_id: coin.coinSource.refreshGroupId,
};
break;
case CoinSourceType.Tip:

View File

@ -250,6 +250,7 @@ export async function importCoin(
coinSource = {
type: CoinSourceType.Refresh,
oldCoinPub: backupCoin.coin_source.old_coin_pub,
refreshGroupId: backupCoin.coin_source.refresh_group_id,
};
break;
case BackupCoinSourceType.Tip:

View File

@ -279,11 +279,21 @@ async function recoupRefreshCoin(
checkDbInvariant(!!oldCoinDenom);
checkDbInvariant(!!revokedCoinDenom);
revokedCoin.status = CoinStatus.Dormant;
recoupGroup.scheduleRefreshCoins.push({
coinPub: oldCoin.coinPub,
//amount: Amounts.sub(oldCoinDenom.value, revokedCoinDenom.value).amount,
amount: revokedCoinDenom.value,
});
if (!revokedCoin.spendAllocation) {
// We don't know what happened to this coin
logger.error(
`can't refresh-recoup coin ${revokedCoin.coinPub}, no spendAllocation known`,
);
} else {
let residualAmount = Amounts.sub(
revokedCoinDenom.value,
revokedCoin.spendAllocation.amount,
).amount;
recoupGroup.scheduleRefreshCoins.push({
coinPub: oldCoin.coinPub,
amount: residualAmount,
});
}
await tx.coins.put(revokedCoin);
await tx.coins.put(oldCoin);
await putGroupAsFinished(ws, tx, recoupGroup, coinIdx);

View File

@ -687,6 +687,7 @@ async function refreshReveal(
status: CoinStatus.Fresh,
coinSource: {
type: CoinSourceType.Refresh,
refreshGroupId,
oldCoinPub: refreshGroup.oldCoinPubs[coinIndex],
},
coinEvHash: pc.coinEvHash,
@ -838,10 +839,6 @@ async function processRefreshSession(
* Refreshes the remaining amount on the coin, effectively capturing the remaining
* value in the refresh group.
*
* The caller must ensure that
* the remaining amount was updated correctly before the coin was deposited or
* credited.
*
* The caller must also ensure that the coins that should be refreshed exist
* in the current database transaction.
*/
@ -893,6 +890,10 @@ export async function createRefreshGroup(
);
switch (coin.status) {
case CoinStatus.Dormant:
coin.spendAllocation = {
amount: Amounts.stringify(ocp.amount),
id: `txn:refresh:${refreshGroupId}`,
};
break;
case CoinStatus.Fresh: {
coin.status = CoinStatus.Dormant;
@ -911,6 +912,10 @@ export async function createRefreshGroup(
// For suspended coins, we don't have to adjust coin
// availability, as they are not counted as available.
coin.status = CoinStatus.Dormant;
coin.spendAllocation = {
amount: Amounts.stringify(ocp.amount),
id: `txn:refresh:${refreshGroupId}`,
};
break;
}
default: