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);
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) {
this.alloc();
// We need to get the javascript string
@ -286,6 +292,14 @@ class AmountNbo extends PackedArenaObject {
size() {
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 {
static create(a) {
@ -468,6 +482,19 @@ class SignatureStruct {
let ba = new ByteArray(totalSize, buf, a);
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) {
let typemap = {};
for (let f of this.fieldTypes()) {

View File

@ -387,6 +387,13 @@ abstract class PackedArenaObject extends ArenaObject {
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) {
this.alloc();
// We need to get the javascript string
@ -420,7 +427,6 @@ abstract class PackedArenaObject extends ArenaObject {
return x;
}
hexdump() {
let bytes: string[] = [];
for (let i = 0; i < this.size(); i++) {
@ -441,6 +447,14 @@ class AmountNbo extends PackedArenaObject {
size() {
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);
}
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) {
let typemap: any = {};
for (let f of this.fieldTypes()) {

View File

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

View File

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