handle multi-coin payments correctly

This commit is contained in:
Florian Dold 2015-12-25 18:48:15 +01:00
parent c51f635673
commit e5cb59e24d
4 changed files with 86 additions and 19 deletions

View File

@ -242,6 +242,12 @@ class PackedArenaObject extends ArenaObject {
emsc.free(d); emsc.free(d);
return s; return s;
} }
toJson() {
// Per default, the json encoding of
// packed arena objects is just the crockford encoding.
// Subclasses typically want to override this.
return this.toCrock();
}
loadCrock(s) { loadCrock(s) {
this.alloc(); this.alloc();
// We need to get the javascript string // We need to get the javascript string
@ -286,6 +292,14 @@ class AmountNbo extends PackedArenaObject {
size() { size() {
return 24; return 24;
} }
toJson() {
let a = new DefaultArena();
let am = new Amount(null, a);
am.fromNbo(this);
let json = am.toJson();
a.destroy();
return json;
}
} }
class EddsaPrivateKey extends PackedArenaObject { class EddsaPrivateKey extends PackedArenaObject {
static create(a) { static create(a) {
@ -468,6 +482,19 @@ class SignatureStruct {
let ba = new ByteArray(totalSize, buf, a); let ba = new ByteArray(totalSize, buf, a);
return new EccSignaturePurpose(this.purpose(), ba); return new EccSignaturePurpose(this.purpose(), ba);
} }
toJson() {
let res = {};
for (let f of this.fieldTypes()) {
let name = f[0];
let member = this.members[name];
if (!member) {
throw Error(format("Member {0} not set", name));
}
res[name] = member.toJson();
}
res["purpose"] = this.purpose();
return res;
}
set(name, value) { set(name, value) {
let typemap = {}; let typemap = {};
for (let f of this.fieldTypes()) { for (let f of this.fieldTypes()) {

View File

@ -387,6 +387,13 @@ abstract class PackedArenaObject extends ArenaObject {
return s; return s;
} }
toJson(): any {
// Per default, the json encoding of
// packed arena objects is just the crockford encoding.
// Subclasses typically want to override this.
return this.toCrock();
}
loadCrock(s: string) { loadCrock(s: string) {
this.alloc(); this.alloc();
// We need to get the javascript string // We need to get the javascript string
@ -420,7 +427,6 @@ abstract class PackedArenaObject extends ArenaObject {
return x; return x;
} }
hexdump() { hexdump() {
let bytes: string[] = []; let bytes: string[] = [];
for (let i = 0; i < this.size(); i++) { for (let i = 0; i < this.size(); i++) {
@ -441,6 +447,14 @@ class AmountNbo extends PackedArenaObject {
size() { size() {
return 24; return 24;
} }
toJson(): any {
let a = new DefaultArena();
let am = new Amount(null, a);
am.fromNbo(this);
let json = am.toJson();
a.destroy();
return json;
}
} }
@ -673,6 +687,21 @@ abstract class SignatureStruct {
return new EccSignaturePurpose(this.purpose(), ba); return new EccSignaturePurpose(this.purpose(), ba);
} }
toJson() {
let res: any = {};
for (let f of this.fieldTypes()) {
let name = f[0];
let member = this.members[name];
if (!member) {
throw Error(format("Member {0} not set", name));
}
res[name] = member.toJson();
}
res["purpose"] = this.purpose();
return res;
}
protected set(name: string, value: PackedArenaObject) { protected set(name: string, value: PackedArenaObject) {
let typemap: any = {}; let typemap: any = {};
for (let f of this.fieldTypes()) { for (let f of this.fieldTypes()) {

View File

@ -34,21 +34,24 @@ function signDeposit(db, offer, cds) {
} }
amountSpent.add(coinSpend); amountSpent.add(coinSpend);
amountRemaining.sub(coinSpend); amountRemaining.sub(coinSpend);
let d = new DepositRequestPS({ let newAmount = new Amount(cd.coin.currentAmount);
newAmount.sub(coinSpend);
cd.coin.currentAmount = newAmount.toJson();
let args = {
h_contract: HashCode.fromCrock(offer.H_contract), h_contract: HashCode.fromCrock(offer.H_contract),
h_wire: HashCode.fromCrock(offer.contract.H_wire), h_wire: HashCode.fromCrock(offer.contract.H_wire),
amount_with_fee: new Amount(cd.coin.currentAmount).toNbo(), amount_with_fee: coinSpend.toNbo(),
coin_pub: EddsaPublicKey.fromCrock(cd.coin.coinPub), coin_pub: EddsaPublicKey.fromCrock(cd.coin.coinPub),
deposit_fee: new Amount(cd.denom.fee_deposit).toNbo(), deposit_fee: new Amount(cd.denom.fee_deposit).toNbo(),
merchant: EddsaPublicKey.fromCrock(offer.contract.merchant_pub), merchant: EddsaPublicKey.fromCrock(offer.contract.merchant_pub),
refund_deadline: AbsoluteTimeNbo.fromTalerString(offer.contract.refund_deadline), refund_deadline: AbsoluteTimeNbo.fromTalerString(offer.contract.refund_deadline),
timestamp: AbsoluteTimeNbo.fromTalerString(offer.contract.timestamp), timestamp: AbsoluteTimeNbo.fromTalerString(offer.contract.timestamp),
transaction_id: UInt64.fromNumber(offer.contract.transaction_id), transaction_id: UInt64.fromNumber(offer.contract.transaction_id),
}); };
let newAmount = new Amount(cd.coin.currentAmount); let d = new DepositRequestPS(args);
newAmount.sub(coinSpend); console.log("Deposit request #" + ret.length);
cd.coin.currentAmount = newAmount.toJson(); console.log("DepositRequestPS: \n", d.toJson());
console.log("DepositRequestPS: ", d.toPurpose().hexdump()); console.log("DepositRequestPS sig: \n", d.toPurpose().hexdump());
let coinSig = eddsaSign(d.toPurpose(), EddsaPrivateKey.fromCrock(cd.coin.coinPriv)) let coinSig = eddsaSign(d.toPurpose(), EddsaPrivateKey.fromCrock(cd.coin.coinPriv))
.toCrock(); .toCrock();
let s = { let s = {
@ -56,7 +59,7 @@ function signDeposit(db, offer, cds) {
coin_pub: cd.coin.coinPub, coin_pub: cd.coin.coinPub,
ub_sig: cd.coin.denomSig, ub_sig: cd.coin.denomSig,
denom_pub: cd.coin.denomPub, denom_pub: cd.coin.denomPub,
f: amountSpent.toJson(), f: coinSpend.toJson(),
}; };
ret.push({ sig: s, updatedCoin: cd.coin }); ret.push({ sig: s, updatedCoin: cd.coin });
} }
@ -126,6 +129,7 @@ function getPossibleMintCoins(db, paymentAmount, depositFeeLimit, allowedMints)
let minAmount = new Amount(paymentAmount); let minAmount = new Amount(paymentAmount);
let accFee = new Amount(coins[0].c.denom.fee_deposit); let accFee = new Amount(coins[0].c.denom.fee_deposit);
let accAmount = Amount.getZero(coins[0].c.coin.currentAmount.currency); let accAmount = Amount.getZero(coins[0].c.coin.currentAmount.currency);
let usableCoins = [];
nextCoin: for (let i = 0; i < coins.length; i++) { nextCoin: for (let i = 0; i < coins.length; i++) {
let coinAmount = new Amount(coins[i].c.coin.currentAmount); let coinAmount = new Amount(coins[i].c.coin.currentAmount);
let coinFee = coins[i].a; let coinFee = coins[i].a;
@ -138,8 +142,9 @@ function getPossibleMintCoins(db, paymentAmount, depositFeeLimit, allowedMints)
console.log("too much fees"); console.log("too much fees");
continue nextMint; continue nextMint;
} }
usableCoins.push(coins[i].c);
if (accAmount.cmp(minAmount) >= 0) { if (accAmount.cmp(minAmount) >= 0) {
ret[key] = m[key]; ret[key] = usableCoins;
continue nextMint; continue nextMint;
} }
} }

View File

@ -97,23 +97,27 @@ function signDeposit(db: IDBDatabase,
amountSpent.add(coinSpend); amountSpent.add(coinSpend);
amountRemaining.sub(coinSpend); amountRemaining.sub(coinSpend);
let d = new DepositRequestPS({ let newAmount = new Amount(cd.coin.currentAmount);
newAmount.sub(coinSpend);
cd.coin.currentAmount = newAmount.toJson();
let args: DepositRequestPS_Args = {
h_contract: HashCode.fromCrock(offer.H_contract), h_contract: HashCode.fromCrock(offer.H_contract),
h_wire: HashCode.fromCrock(offer.contract.H_wire), h_wire: HashCode.fromCrock(offer.contract.H_wire),
amount_with_fee: new Amount(cd.coin.currentAmount).toNbo(), amount_with_fee: coinSpend.toNbo(),
coin_pub: EddsaPublicKey.fromCrock(cd.coin.coinPub), coin_pub: EddsaPublicKey.fromCrock(cd.coin.coinPub),
deposit_fee: new Amount(cd.denom.fee_deposit).toNbo(), deposit_fee: new Amount(cd.denom.fee_deposit).toNbo(),
merchant: EddsaPublicKey.fromCrock(offer.contract.merchant_pub), merchant: EddsaPublicKey.fromCrock(offer.contract.merchant_pub),
refund_deadline: AbsoluteTimeNbo.fromTalerString(offer.contract.refund_deadline), refund_deadline: AbsoluteTimeNbo.fromTalerString(offer.contract.refund_deadline),
timestamp: AbsoluteTimeNbo.fromTalerString(offer.contract.timestamp), timestamp: AbsoluteTimeNbo.fromTalerString(offer.contract.timestamp),
transaction_id: UInt64.fromNumber(offer.contract.transaction_id), transaction_id: UInt64.fromNumber(offer.contract.transaction_id),
}); };
let newAmount = new Amount(cd.coin.currentAmount); let d = new DepositRequestPS(args);
newAmount.sub(coinSpend);
cd.coin.currentAmount = newAmount.toJson();
console.log("DepositRequestPS: ", d.toPurpose().hexdump()); console.log("Deposit request #" + ret.length);
console.log("DepositRequestPS: \n", d.toJson());
console.log("DepositRequestPS sig: \n", d.toPurpose().hexdump());
let coinSig = eddsaSign(d.toPurpose(), let coinSig = eddsaSign(d.toPurpose(),
EddsaPrivateKey.fromCrock(cd.coin.coinPriv)) EddsaPrivateKey.fromCrock(cd.coin.coinPriv))
@ -124,7 +128,7 @@ function signDeposit(db: IDBDatabase,
coin_pub: cd.coin.coinPub, coin_pub: cd.coin.coinPub,
ub_sig: cd.coin.denomSig, ub_sig: cd.coin.denomSig,
denom_pub: cd.coin.denomPub, denom_pub: cd.coin.denomPub,
f: amountSpent.toJson(), f: coinSpend.toJson(),
}; };
ret.push({sig: s, updatedCoin: cd.coin}); ret.push({sig: s, updatedCoin: cd.coin});
} }
@ -206,6 +210,7 @@ function getPossibleMintCoins(db: IDBDatabase,
let minAmount = new Amount(paymentAmount); let minAmount = new Amount(paymentAmount);
let accFee = new Amount(coins[0].c.denom.fee_deposit); let accFee = new Amount(coins[0].c.denom.fee_deposit);
let accAmount = Amount.getZero(coins[0].c.coin.currentAmount.currency); let accAmount = Amount.getZero(coins[0].c.coin.currentAmount.currency);
let usableCoins: Db.CoinWithDenom[] = [];
nextCoin: nextCoin:
for (let i = 0; i < coins.length; i++) { for (let i = 0; i < coins.length; i++) {
let coinAmount = new Amount(coins[i].c.coin.currentAmount); let coinAmount = new Amount(coins[i].c.coin.currentAmount);
@ -219,8 +224,9 @@ function getPossibleMintCoins(db: IDBDatabase,
console.log("too much fees"); console.log("too much fees");
continue nextMint; continue nextMint;
} }
usableCoins.push(coins[i].c);
if (accAmount.cmp(minAmount) >= 0) { if (accAmount.cmp(minAmount) >= 0) {
ret[key] = m[key]; ret[key] = usableCoins;
continue nextMint; continue nextMint;
} }
} }