working refresh prototype
This commit is contained in:
parent
0b198e0888
commit
ab53892231
File diff suppressed because one or more lines are too long
@ -114,7 +114,8 @@ export class CryptoApi {
|
|||||||
|
|
||||||
handleWorkerError(ws: WorkerState, e: ErrorEvent) {
|
handleWorkerError(ws: WorkerState, e: ErrorEvent) {
|
||||||
if (ws.currentWorkItem) {
|
if (ws.currentWorkItem) {
|
||||||
console.error(`error in worker during ${ws.currentWorkItem!.operation}`, e);
|
console.error(`error in worker during ${ws.currentWorkItem!.operation}`,
|
||||||
|
e);
|
||||||
} else {
|
} else {
|
||||||
console.error("error in worker", e);
|
console.error("error in worker", e);
|
||||||
}
|
}
|
||||||
@ -243,16 +244,17 @@ export class CryptoApi {
|
|||||||
return this.doRpc("rsaUnblind", 4, sig, bk, pk);
|
return this.doRpc("rsaUnblind", 4, sig, bk, pk);
|
||||||
}
|
}
|
||||||
|
|
||||||
createWithdrawSession(kappa: number, meltCoin: Coin,
|
createRefreshSession(exchangeBaseUrl: string,
|
||||||
newCoinDenoms: Denomination[],
|
kappa: number,
|
||||||
meltAmount: AmountJson,
|
meltCoin: Coin,
|
||||||
meltFee: AmountJson): Promise<RefreshSession> {
|
newCoinDenoms: Denomination[],
|
||||||
return this.doRpc("createWithdrawSession",
|
meltFee: AmountJson): Promise<RefreshSession> {
|
||||||
|
return this.doRpc("createRefreshSession",
|
||||||
4,
|
4,
|
||||||
|
exchangeBaseUrl,
|
||||||
kappa,
|
kappa,
|
||||||
meltCoin,
|
meltCoin,
|
||||||
newCoinDenoms,
|
newCoinDenoms,
|
||||||
meltAmount,
|
|
||||||
meltFee);
|
meltFee);
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -30,7 +30,7 @@ import create = chrome.alarms.create;
|
|||||||
import {Offer} from "./wallet";
|
import {Offer} from "./wallet";
|
||||||
import {CoinWithDenom} from "./wallet";
|
import {CoinWithDenom} from "./wallet";
|
||||||
import {CoinPaySig} from "./types";
|
import {CoinPaySig} from "./types";
|
||||||
import {Denomination} from "./types";
|
import {Denomination, Amounts} from "./types";
|
||||||
import {Amount} from "./emscriptif";
|
import {Amount} from "./emscriptif";
|
||||||
import {Coin} from "../../background/lib/wallet/types";
|
import {Coin} from "../../background/lib/wallet/types";
|
||||||
import {HashContext} from "./emscriptif";
|
import {HashContext} from "./emscriptif";
|
||||||
@ -151,11 +151,6 @@ namespace RpcFunctions {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function hashString(str: string): string {
|
|
||||||
const b = native.ByteArray.fromString(str);
|
|
||||||
return b.hash().toCrock();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
export function hashRsaPub(rsaPub: string): string {
|
export function hashRsaPub(rsaPub: string): string {
|
||||||
return native.RsaPublicKey.fromCrock(rsaPub)
|
return native.RsaPublicKey.fromCrock(rsaPub)
|
||||||
@ -238,21 +233,36 @@ namespace RpcFunctions {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
export function createWithdrawSession(kappa: number, meltCoin: Coin,
|
export function createRefreshSession(exchangeBaseUrl: string,
|
||||||
newCoinDenoms: Denomination[],
|
kappa: number,
|
||||||
meltAmount: AmountJson,
|
meltCoin: Coin,
|
||||||
meltFee: AmountJson): RefreshSession {
|
newCoinDenoms: Denomination[],
|
||||||
|
meltFee: AmountJson): RefreshSession {
|
||||||
|
|
||||||
|
let valueWithFee = Amounts.getZero(newCoinDenoms[0].value.currency);
|
||||||
|
|
||||||
|
for (let ncd of newCoinDenoms) {
|
||||||
|
valueWithFee = Amounts.add(valueWithFee,
|
||||||
|
ncd.value,
|
||||||
|
ncd.fee_withdraw).amount;
|
||||||
|
}
|
||||||
|
|
||||||
|
// melt fee
|
||||||
|
valueWithFee = Amounts.add(valueWithFee, meltFee).amount;
|
||||||
|
|
||||||
let sessionHc = new HashContext();
|
let sessionHc = new HashContext();
|
||||||
|
|
||||||
let transferPubs: string[] = [];
|
let transferPubs: string[] = [];
|
||||||
|
let transferPrivs: string[] = [];
|
||||||
|
|
||||||
let preCoinsForGammas: RefreshPreCoin[][] = [];
|
let preCoinsForGammas: RefreshPreCoin[][] = [];
|
||||||
|
|
||||||
for (let i = 0; i < newCoinDenoms.length; i++) {
|
for (let i = 0; i < kappa; i++) {
|
||||||
let t = native.EcdsaPrivateKey.create();
|
let t = native.EcdhePrivateKey.create();
|
||||||
sessionHc.read(t);
|
let pub = t.getPublicKey();
|
||||||
transferPubs.push(t.toCrock());
|
sessionHc.read(pub);
|
||||||
|
transferPrivs.push(t.toCrock());
|
||||||
|
transferPubs.push(pub.toCrock());
|
||||||
}
|
}
|
||||||
|
|
||||||
for (let i = 0; i < newCoinDenoms.length; i++) {
|
for (let i = 0; i < newCoinDenoms.length; i++) {
|
||||||
@ -260,18 +270,24 @@ namespace RpcFunctions {
|
|||||||
sessionHc.read(r.encode());
|
sessionHc.read(r.encode());
|
||||||
}
|
}
|
||||||
|
|
||||||
sessionHc.read(native.RsaPublicKey.fromCrock(meltCoin.coinPub).encode());
|
sessionHc.read(native.EddsaPublicKey.fromCrock(meltCoin.coinPub));
|
||||||
sessionHc.read((new native.Amount(meltAmount)).toNbo());
|
sessionHc.read((new native.Amount(valueWithFee)).toNbo());
|
||||||
|
|
||||||
for (let j = 0; j < kappa; j++) {
|
for (let i = 0; i < kappa; i++) {
|
||||||
let preCoins: RefreshPreCoin[] = [];
|
let preCoins: RefreshPreCoin[] = [];
|
||||||
for (let i = 0; i < newCoinDenoms.length; i++) {
|
for (let j = 0; j < newCoinDenoms.length; j++) {
|
||||||
|
|
||||||
let coinPriv = native.EddsaPrivateKey.create();
|
let transferPriv = native.EcdhePrivateKey.fromCrock(transferPrivs[i]);
|
||||||
|
let oldCoinPub = native.EddsaPublicKey.fromCrock(meltCoin.coinPub);
|
||||||
|
let transferSecret = native.ecdhEddsa(transferPriv, oldCoinPub);
|
||||||
|
|
||||||
|
let fresh = native.setupFreshCoin(transferSecret, j);
|
||||||
|
|
||||||
|
let coinPriv = fresh.priv;
|
||||||
let coinPub = coinPriv.getPublicKey();
|
let coinPub = coinPriv.getPublicKey();
|
||||||
let blindingFactor = native.RsaBlindingKeySecret.create();
|
let blindingFactor = fresh.blindingKey;
|
||||||
let pubHash: native.HashCode = coinPub.hash();
|
let pubHash: native.HashCode = coinPub.hash();
|
||||||
let denomPub = native.RsaPublicKey.fromCrock(newCoinDenoms[i].denom_pub);
|
let denomPub = native.RsaPublicKey.fromCrock(newCoinDenoms[j].denom_pub);
|
||||||
let ev = native.rsaBlind(pubHash,
|
let ev = native.rsaBlind(pubHash,
|
||||||
blindingFactor,
|
blindingFactor,
|
||||||
denomPub);
|
denomPub);
|
||||||
@ -296,11 +312,12 @@ namespace RpcFunctions {
|
|||||||
|
|
||||||
let confirmData = new RefreshMeltCoinAffirmationPS({
|
let confirmData = new RefreshMeltCoinAffirmationPS({
|
||||||
coin_pub: EddsaPublicKey.fromCrock(meltCoin.coinPub),
|
coin_pub: EddsaPublicKey.fromCrock(meltCoin.coinPub),
|
||||||
amount_with_fee: (new Amount(meltAmount)).toNbo(),
|
amount_with_fee: (new Amount(valueWithFee)).toNbo(),
|
||||||
session_hash: sessionHash,
|
session_hash: sessionHash,
|
||||||
melt_fee: (new Amount(meltFee)).toNbo()
|
melt_fee: (new Amount(meltFee)).toNbo()
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
let confirmSig: string = native.eddsaSign(confirmData.toPurpose(),
|
let confirmSig: string = native.eddsaSign(confirmData.toPurpose(),
|
||||||
native.EddsaPrivateKey.fromCrock(
|
native.EddsaPrivateKey.fromCrock(
|
||||||
meltCoin.coinPriv)).toCrock();
|
meltCoin.coinPriv)).toCrock();
|
||||||
@ -309,9 +326,13 @@ namespace RpcFunctions {
|
|||||||
meltCoinPub: meltCoin.coinPub,
|
meltCoinPub: meltCoin.coinPub,
|
||||||
newDenoms: newCoinDenoms.map((d) => d.denom_pub),
|
newDenoms: newCoinDenoms.map((d) => d.denom_pub),
|
||||||
confirmSig,
|
confirmSig,
|
||||||
valueWithFee: meltAmount,
|
valueWithFee,
|
||||||
transferPubs,
|
transferPubs,
|
||||||
preCoinsForGammas,
|
preCoinsForGammas,
|
||||||
|
hash: sessionHash.toCrock(),
|
||||||
|
norevealIndex: undefined,
|
||||||
|
exchangeBaseUrl,
|
||||||
|
transferPrivs,
|
||||||
};
|
};
|
||||||
|
|
||||||
return refreshSession;
|
return refreshSession;
|
||||||
|
@ -36,9 +36,18 @@ const GNUNET_SYSERR = -1;
|
|||||||
|
|
||||||
let Module = EmscWrapper.Module;
|
let Module = EmscWrapper.Module;
|
||||||
|
|
||||||
let getEmsc: EmscWrapper.EmscFunGen = (...args: any[]) => Module.cwrap.apply(
|
|
||||||
null,
|
function myCcall(name: string, ret: any, argTypes: any[], args: any[]) {
|
||||||
args);
|
return Module.ccall(name, ret, argTypes, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
let getEmsc: EmscWrapper.EmscFunGen = (name: string, ret: any,
|
||||||
|
argTypes: any[]) => {
|
||||||
|
return (...args: any[]) => {
|
||||||
|
return myCcall(name, ret, argTypes, args);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
var emsc = {
|
var emsc = {
|
||||||
free: (ptr: number) => Module._free(ptr),
|
free: (ptr: number) => Module._free(ptr),
|
||||||
@ -111,6 +120,15 @@ var emsc = {
|
|||||||
hash_context_finish: getEmsc('GNUNET_CRYPTO_hash_context_finish',
|
hash_context_finish: getEmsc('GNUNET_CRYPTO_hash_context_finish',
|
||||||
'void',
|
'void',
|
||||||
['number', 'number']),
|
['number', 'number']),
|
||||||
|
ecdh_eddsa: getEmsc(
|
||||||
|
"GNUNET_CRYPTO_ecdh_eddsa",
|
||||||
|
'number',
|
||||||
|
["number", "number", "number"]),
|
||||||
|
|
||||||
|
setup_fresh_coin: getEmsc(
|
||||||
|
"TALER_setup_fresh_coin",
|
||||||
|
'void',
|
||||||
|
["number", "number", "number"]),
|
||||||
};
|
};
|
||||||
|
|
||||||
var emscAlloc = {
|
var emscAlloc = {
|
||||||
@ -121,6 +139,8 @@ var emscAlloc = {
|
|||||||
'number', []),
|
'number', []),
|
||||||
ecdsa_key_create: getEmsc('GNUNET_CRYPTO_ecdsa_key_create',
|
ecdsa_key_create: getEmsc('GNUNET_CRYPTO_ecdsa_key_create',
|
||||||
'number', []),
|
'number', []),
|
||||||
|
ecdhe_key_create: getEmsc('GNUNET_CRYPTO_ecdhe_key_create',
|
||||||
|
'number', []),
|
||||||
eddsa_public_key_from_private: getEmsc(
|
eddsa_public_key_from_private: getEmsc(
|
||||||
'TALER_WRALL_eddsa_public_key_from_private',
|
'TALER_WRALL_eddsa_public_key_from_private',
|
||||||
'number',
|
'number',
|
||||||
@ -129,6 +149,10 @@ var emscAlloc = {
|
|||||||
'TALER_WRALL_ecdsa_public_key_from_private',
|
'TALER_WRALL_ecdsa_public_key_from_private',
|
||||||
'number',
|
'number',
|
||||||
['number']),
|
['number']),
|
||||||
|
ecdhe_public_key_from_private: getEmsc(
|
||||||
|
'TALER_WRALL_ecdhe_public_key_from_private',
|
||||||
|
'number',
|
||||||
|
['number']),
|
||||||
data_to_string_alloc: getEmsc('GNUNET_STRINGS_data_to_string_alloc',
|
data_to_string_alloc: getEmsc('GNUNET_STRINGS_data_to_string_alloc',
|
||||||
'number',
|
'number',
|
||||||
['number', 'number']),
|
['number', 'number']),
|
||||||
@ -512,7 +536,7 @@ abstract class PackedArenaObject extends MallocArenaObject {
|
|||||||
this.alloc();
|
this.alloc();
|
||||||
// We need to get the javascript string
|
// We need to get the javascript string
|
||||||
// to the emscripten heap first.
|
// to the emscripten heap first.
|
||||||
let buf = ByteArray.fromString(s);
|
let buf = ByteArray.fromStringWithNull(s);
|
||||||
let res = emsc.string_to_data(buf.nativePtr,
|
let res = emsc.string_to_data(buf.nativePtr,
|
||||||
s.length,
|
s.length,
|
||||||
this.nativePtr,
|
this.nativePtr,
|
||||||
@ -618,6 +642,28 @@ export class EcdsaPrivateKey extends PackedArenaObject {
|
|||||||
mixinStatic(EcdsaPrivateKey, fromCrock);
|
mixinStatic(EcdsaPrivateKey, fromCrock);
|
||||||
|
|
||||||
|
|
||||||
|
export class EcdhePrivateKey extends PackedArenaObject {
|
||||||
|
static create(a?: Arena): EcdhePrivateKey {
|
||||||
|
let obj = new EcdhePrivateKey(a);
|
||||||
|
obj.nativePtr = emscAlloc.ecdhe_key_create();
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
size() {
|
||||||
|
return 32;
|
||||||
|
}
|
||||||
|
|
||||||
|
getPublicKey(a?: Arena): EcdhePublicKey {
|
||||||
|
let obj = new EcdhePublicKey(a);
|
||||||
|
obj.nativePtr = emscAlloc.ecdhe_public_key_from_private(this.nativePtr);
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
static fromCrock: (s: string) => EcdhePrivateKey;
|
||||||
|
}
|
||||||
|
mixinStatic(EcdhePrivateKey, fromCrock);
|
||||||
|
|
||||||
|
|
||||||
function fromCrock(s: string) {
|
function fromCrock(s: string) {
|
||||||
let x = new this();
|
let x = new this();
|
||||||
x.alloc();
|
x.alloc();
|
||||||
@ -664,7 +710,17 @@ export class EcdsaPublicKey extends PackedArenaObject {
|
|||||||
|
|
||||||
static fromCrock: (s: string) => EcdsaPublicKey;
|
static fromCrock: (s: string) => EcdsaPublicKey;
|
||||||
}
|
}
|
||||||
mixinStatic(EddsaPublicKey, fromCrock);
|
mixinStatic(EcdsaPublicKey, fromCrock);
|
||||||
|
|
||||||
|
|
||||||
|
export class EcdhePublicKey extends PackedArenaObject {
|
||||||
|
size() {
|
||||||
|
return 32;
|
||||||
|
}
|
||||||
|
|
||||||
|
static fromCrock: (s: string) => EcdhePublicKey;
|
||||||
|
}
|
||||||
|
mixinStatic(EcdhePublicKey, fromCrock);
|
||||||
|
|
||||||
|
|
||||||
function makeFromCrock(decodeFn: (p: number, s: number) => number) {
|
function makeFromCrock(decodeFn: (p: number, s: number) => number) {
|
||||||
@ -747,7 +803,15 @@ export class ByteArray extends PackedArenaObject {
|
|||||||
this.allocatedSize = desiredSize;
|
this.allocatedSize = desiredSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
static fromString(s: string, a?: Arena): ByteArray {
|
static fromStringWithoutNull(s: string, a?: Arena): ByteArray {
|
||||||
|
// UTF-8 bytes, including 0-terminator
|
||||||
|
let terminatedByteLength = countUtf8Bytes(s) + 1;
|
||||||
|
let hstr = emscAlloc.malloc(terminatedByteLength);
|
||||||
|
Module.stringToUTF8(s, hstr, terminatedByteLength);
|
||||||
|
return new ByteArray(terminatedByteLength - 1, hstr, a);
|
||||||
|
}
|
||||||
|
|
||||||
|
static fromStringWithNull(s: string, a?: Arena): ByteArray {
|
||||||
// UTF-8 bytes, including 0-terminator
|
// UTF-8 bytes, including 0-terminator
|
||||||
let terminatedByteLength = countUtf8Bytes(s) + 1;
|
let terminatedByteLength = countUtf8Bytes(s) + 1;
|
||||||
let hstr = emscAlloc.malloc(terminatedByteLength);
|
let hstr = emscAlloc.malloc(terminatedByteLength);
|
||||||
@ -978,7 +1042,7 @@ export class UInt32 extends PackedArenaObject {
|
|||||||
}
|
}
|
||||||
|
|
||||||
size() {
|
size() {
|
||||||
return 8;
|
return 4;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1185,51 +1249,36 @@ export function rsaUnblind(sig: RsaSignature,
|
|||||||
|
|
||||||
type TransferSecretP = HashCode;
|
type TransferSecretP = HashCode;
|
||||||
|
|
||||||
export function kdf(outLength: number,
|
|
||||||
salt: PackedArenaObject,
|
|
||||||
skm: PackedArenaObject,
|
|
||||||
...contextChunks: PackedArenaObject[]): ByteArray {
|
|
||||||
const args: number[] = [];
|
|
||||||
let out = new ByteArray(outLength);
|
|
||||||
args.push(out.nativePtr, outLength);
|
|
||||||
args.push(salt.nativePtr, salt.size());
|
|
||||||
args.push(skm.nativePtr, skm.size());
|
|
||||||
for (let chunk of contextChunks) {
|
|
||||||
args.push(chunk.nativePtr, chunk.size());
|
|
||||||
}
|
|
||||||
// end terminator (it's varargs)
|
|
||||||
args.push(0);
|
|
||||||
args.push(0);
|
|
||||||
|
|
||||||
let argTypes = args.map(() => "number");
|
|
||||||
|
|
||||||
const res = Module.ccall("GNUNET_CRYPTO_kdf", "number", argTypes, args);
|
|
||||||
if (res != GNUNET_OK) {
|
|
||||||
throw Error("fatal: kdf failed");
|
|
||||||
}
|
|
||||||
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
export interface FreshCoin {
|
export interface FreshCoin {
|
||||||
priv: EddsaPrivateKey;
|
priv: EddsaPrivateKey;
|
||||||
blindingKey: RsaBlindingKeySecret;
|
blindingKey: RsaBlindingKeySecret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function ecdhEddsa(priv: EcdhePrivateKey,
|
||||||
|
pub: EddsaPublicKey): HashCode {
|
||||||
|
let h = new HashCode();
|
||||||
|
h.alloc();
|
||||||
|
let res = emsc.ecdh_eddsa(priv.nativePtr, pub.nativePtr, h.nativePtr);
|
||||||
|
if (res != GNUNET_OK) {
|
||||||
|
throw Error("ecdh_eddsa failed");
|
||||||
|
}
|
||||||
|
return h;
|
||||||
|
}
|
||||||
|
|
||||||
export function setupFreshCoin(secretSeed: TransferSecretP,
|
export function setupFreshCoin(secretSeed: TransferSecretP,
|
||||||
coinIndex: number): FreshCoin {
|
coinIndex: number): FreshCoin {
|
||||||
let priv = new EddsaPrivateKey();
|
let priv = new EddsaPrivateKey();
|
||||||
priv.isWeak = true;
|
priv.isWeak = true;
|
||||||
let blindingKey = new RsaBlindingKeySecret();
|
let blindingKey = new RsaBlindingKeySecret();
|
||||||
blindingKey.isWeak = true;
|
blindingKey.isWeak = true;
|
||||||
|
let buf = new ByteArray(priv.size() + blindingKey.size());
|
||||||
|
|
||||||
let buf = kdf(priv.size() + blindingKey.size(),
|
emsc.setup_fresh_coin(secretSeed.nativePtr, coinIndex, buf.nativePtr);
|
||||||
UInt32.fromNumber(coinIndex),
|
|
||||||
ByteArray.fromString("taler-coin-derivation"));
|
|
||||||
|
|
||||||
priv.nativePtr = buf.nativePtr;
|
priv.nativePtr = buf.nativePtr;
|
||||||
blindingKey.nativePtr = buf.nativePtr + priv.size();
|
blindingKey.nativePtr = buf.nativePtr + priv.size();
|
||||||
|
|
||||||
return {priv, blindingKey};
|
return {priv, blindingKey};
|
||||||
|
|
||||||
}
|
}
|
@ -212,6 +212,20 @@ export interface RefreshSession {
|
|||||||
* The transfer keys, kappa of them.
|
* The transfer keys, kappa of them.
|
||||||
*/
|
*/
|
||||||
transferPubs: string[];
|
transferPubs: string[];
|
||||||
|
|
||||||
|
transferPrivs: string[];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The no-reveal-index after we've done the melting.
|
||||||
|
*/
|
||||||
|
norevealIndex?: number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hash of the session.
|
||||||
|
*/
|
||||||
|
hash: string;
|
||||||
|
|
||||||
|
exchangeBaseUrl: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1121,27 +1121,89 @@ export class Wallet {
|
|||||||
|
|
||||||
let availableDenoms: Denomination[] = exchange.active_denoms;
|
let availableDenoms: Denomination[] = exchange.active_denoms;
|
||||||
|
|
||||||
let newCoinDenoms = getWithdrawDenomList(coin.currentAmount,
|
let availableAmount = Amounts.sub(coin.currentAmount,
|
||||||
|
oldDenom.fee_refresh).amount;
|
||||||
|
|
||||||
|
let newCoinDenoms = getWithdrawDenomList(availableAmount,
|
||||||
availableDenoms);
|
availableDenoms);
|
||||||
|
|
||||||
|
newCoinDenoms = [newCoinDenoms[0]];
|
||||||
console.log("refreshing into", newCoinDenoms);
|
console.log("refreshing into", newCoinDenoms);
|
||||||
|
|
||||||
|
|
||||||
let refreshSession: RefreshSession = await (
|
let refreshSession: RefreshSession = await (
|
||||||
this.cryptoApi.createWithdrawSession(3,
|
this.cryptoApi.createRefreshSession(exchange.baseUrl,
|
||||||
|
3,
|
||||||
coin,
|
coin,
|
||||||
newCoinDenoms,
|
newCoinDenoms,
|
||||||
coin.currentAmount,
|
|
||||||
oldDenom.fee_refresh));
|
oldDenom.fee_refresh));
|
||||||
|
|
||||||
let reqUrl = URI("reserve/withdraw").absoluteTo(exchange!.baseUrl);
|
let reqUrl = URI("refresh/melt").absoluteTo(exchange!.baseUrl);
|
||||||
let resp = await this.http.postJson(reqUrl, {});
|
let meltCoin = {
|
||||||
|
coin_pub: coin.coinPub,
|
||||||
|
denom_pub: coin.denomPub,
|
||||||
|
denom_sig: coin.denomSig,
|
||||||
|
confirm_sig: refreshSession.confirmSig,
|
||||||
|
value_with_fee: refreshSession.valueWithFee,
|
||||||
|
};
|
||||||
|
let coinEvs = refreshSession.preCoinsForGammas.map((x) => x.map((y) => y.coinEv));
|
||||||
|
let req = {
|
||||||
|
"new_denoms": newCoinDenoms.map((d) => d.denom_pub),
|
||||||
|
"melt_coin": meltCoin,
|
||||||
|
"transfer_pubs": refreshSession.transferPubs,
|
||||||
|
"coin_evs": coinEvs,
|
||||||
|
};
|
||||||
|
console.log("melt request:", req);
|
||||||
|
let resp = await this.http.postJson(reqUrl, req);
|
||||||
|
|
||||||
|
console.log("melt request:", req);
|
||||||
console.log("melt response:", resp.responseText);
|
console.log("melt response:", resp.responseText);
|
||||||
|
|
||||||
|
if (resp.status != 200) {
|
||||||
|
console.error(resp.responseText);
|
||||||
|
throw Error("refresh failed");
|
||||||
|
}
|
||||||
|
|
||||||
|
let respJson = JSON.parse(resp.responseText);
|
||||||
|
|
||||||
|
if (!respJson) {
|
||||||
|
throw Error("exchange responded with garbage");
|
||||||
|
}
|
||||||
|
|
||||||
|
let norevealIndex = respJson.noreveal_index;
|
||||||
|
|
||||||
|
if (typeof norevealIndex != "number") {
|
||||||
|
throw Error("invalid response");
|
||||||
|
}
|
||||||
|
|
||||||
|
refreshSession.norevealIndex = norevealIndex;
|
||||||
|
|
||||||
|
this.refreshReveal(refreshSession);
|
||||||
|
|
||||||
// FIXME: implement rest
|
// FIXME: implement rest
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async refreshReveal(refreshSession: RefreshSession): Promise<void> {
|
||||||
|
let norevealIndex = refreshSession.norevealIndex;
|
||||||
|
if (norevealIndex == undefined) {
|
||||||
|
throw Error("can't reveal without melting first");
|
||||||
|
}
|
||||||
|
let privs = Array.from(refreshSession.transferPrivs);
|
||||||
|
privs.splice(norevealIndex, 1);
|
||||||
|
|
||||||
|
let req = {
|
||||||
|
"session_hash": refreshSession.hash,
|
||||||
|
"transfer_privs": privs,
|
||||||
|
};
|
||||||
|
|
||||||
|
let reqUrl = URI("refresh/reveal").absoluteTo(refreshSession.exchangeBaseUrl);
|
||||||
|
console.log("reveal request:", req);
|
||||||
|
let resp = await this.http.postJson(reqUrl, req);
|
||||||
|
|
||||||
|
console.log("session:", refreshSession);
|
||||||
|
console.log("reveal response:", resp);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrive the full event history for this wallet.
|
* Retrive the full event history for this wallet.
|
||||||
|
Loading…
Reference in New Issue
Block a user