[age-withdraw] WiP: first types and adjustments
This commit is contained in:
parent
819949d7f2
commit
70fca92e78
@ -1254,30 +1254,9 @@ export namespace AgeRestriction {
|
|||||||
age: number,
|
age: number,
|
||||||
): Promise<AgeCommitmentProof> {
|
): Promise<AgeCommitmentProof> {
|
||||||
invariant((ageMask & 1) === 1);
|
invariant((ageMask & 1) === 1);
|
||||||
const numPubs = countAgeGroups(ageMask) - 1;
|
const seed = getRandomBytes(32);
|
||||||
const numPrivs = getAgeGroupIndex(ageMask, age);
|
|
||||||
|
|
||||||
const pubs: Edx25519PublicKey[] = [];
|
return restrictionCommitSeeded(ageMask, age, seed);
|
||||||
const privs: Edx25519PrivateKey[] = [];
|
|
||||||
|
|
||||||
for (let i = 0; i < numPubs; i++) {
|
|
||||||
const priv = await Edx25519.keyCreate();
|
|
||||||
const pub = await Edx25519.getPublic(priv);
|
|
||||||
pubs.push(pub);
|
|
||||||
if (i < numPrivs) {
|
|
||||||
privs.push(priv);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
commitment: {
|
|
||||||
mask: ageMask,
|
|
||||||
publicKeys: pubs.map((x) => encodeCrock(x)),
|
|
||||||
},
|
|
||||||
proof: {
|
|
||||||
privateKeys: privs.map((x) => encodeCrock(x)),
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const PublishedAgeRestrictionBaseKey: Edx25519PublicKey = decodeCrock(
|
const PublishedAgeRestrictionBaseKey: Edx25519PublicKey = decodeCrock(
|
||||||
|
@ -1788,6 +1788,89 @@ export interface ExchangeRefreshRevealRequest {
|
|||||||
old_age_commitment?: Edx25519PublicKeyEnc[];
|
old_age_commitment?: Edx25519PublicKeyEnc[];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface ExchangeAgeWithdrawRequest {
|
||||||
|
// Array of n hash codes of denomination public keys to order.
|
||||||
|
// These denominations MUST support age restriction as defined in the
|
||||||
|
// output to /keys.
|
||||||
|
// The sum of all denomination's values and fees MUST be at most the
|
||||||
|
// balance of the reserve. The balance of the reserve will be
|
||||||
|
// immediatley reduced by that amount.
|
||||||
|
denoms_h: HashCodeString[];
|
||||||
|
|
||||||
|
// n arrays of kappa entries with blinded coin envelopes. Each
|
||||||
|
// (toplevel) entry represents kappa canditates for a particular
|
||||||
|
// coin. The exchange will respond with an index gamma, which is
|
||||||
|
// the index that shall remain undisclosed during the reveal phase.
|
||||||
|
// The SHA512 hash $ACH over the blinded coin envelopes is the commitment
|
||||||
|
// that is later used as the key to the reveal-URL.
|
||||||
|
blinded_coins_evs: CoinEnvelope[][];
|
||||||
|
|
||||||
|
// The maximum age to commit to. MUST be the same as the maximum
|
||||||
|
// age value assigned to the reserve, based on its birthday date.
|
||||||
|
max_age: number;
|
||||||
|
|
||||||
|
// Signature of TALER_AgeWithdrawRequestPS created with
|
||||||
|
// the reserves's private key
|
||||||
|
// using purpose TALER_SIGNATURE_WALLET_RESERVE_AGE_WITHDRAW.
|
||||||
|
reserve_sig: EddsaSignatureString;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ExchangeAgeWithdrawResponse {
|
||||||
|
// index of the commitments that the client doesn't
|
||||||
|
// have to disclose
|
||||||
|
noreveal_index: number;
|
||||||
|
|
||||||
|
// Signature of TALER_AgeWithdrawConfirmationPS whereby
|
||||||
|
// the exchange confirms the noreveal_index.
|
||||||
|
exchange_sig: EddsaSignatureString;
|
||||||
|
|
||||||
|
// Public EdDSA key of the exchange that was used to
|
||||||
|
// generate the signature. Should match one of the exchange's signing
|
||||||
|
// keys from /keys. Again given explicitly as the client might
|
||||||
|
// otherwise be confused by clock skew as to which signing key was used.
|
||||||
|
exchange_pub: EddsaPublicKeyString;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ExchangeAgeWithdrawRevealRequest {
|
||||||
|
// Array of n of (kappa - 1) disclosed coin master secrets, from
|
||||||
|
// which the coins' private key, blinding, nonce (for Clause-Schnorr) and
|
||||||
|
// age-restriction is calculated.
|
||||||
|
//
|
||||||
|
// Given each coin's private key and age commitment, the exchange will
|
||||||
|
// calculate each coin's blinded hash value und use all those (disclosed)
|
||||||
|
// blinded hashes together with the non-disclosed envelopes coin_evs
|
||||||
|
// during the verification of the original age-withdraw-commitment.
|
||||||
|
disclosed_coin_secrets: AgeRestrictedCoinSecret[][];
|
||||||
|
}
|
||||||
|
|
||||||
|
// The Master key material from which the coins' private key coin_priv,
|
||||||
|
// blinding beta and nonce nonce (for Clause-Schnorr) itself are
|
||||||
|
// derived as usually in wallet-core. Given a coin's master key material,
|
||||||
|
// the age commitment for the coin MUST be derived from this private key as
|
||||||
|
// follows:
|
||||||
|
//
|
||||||
|
// Let m ∈ {1,...,M} be the maximum age group as defined in the reserve
|
||||||
|
// that the wallet can commit to.
|
||||||
|
//
|
||||||
|
// For age group $AG ∈ {1,...m}, set
|
||||||
|
// seed = HDKF(coin_secret, "age-commitment", $AG)
|
||||||
|
// p[$AG] = Edx25519_generate_private(seed)
|
||||||
|
// and calculate the corresponding Edx25519PublicKey as
|
||||||
|
// q[$AG] = Edx25519_public_from_private(p[$AG])
|
||||||
|
//
|
||||||
|
// For age groups $AG ∈ {m,...,M}, set
|
||||||
|
// f[$AG] = HDKF(coin_secret, "age-factor", $AG)
|
||||||
|
// and calculate the corresponding Edx25519PublicKey as
|
||||||
|
// q[$AG] = Edx25519_derive_public(PublishedAgeRestrictionBaseKey, f[$AG])
|
||||||
|
//
|
||||||
|
// FIXME: shall we add some flavor to this string?
|
||||||
|
export type AgeRestrictedCoinSecret = string;
|
||||||
|
|
||||||
|
export interface ExchangeAgeWithdrawRevealResponse {
|
||||||
|
// List of the exchange's blinded RSA or CS signatures on the new coins.
|
||||||
|
ev_sigs : BlindedDenominationSignature[];
|
||||||
|
}
|
||||||
|
|
||||||
export interface DepositSuccess {
|
export interface DepositSuccess {
|
||||||
// Optional base URL of the exchange for looking up wire transfers
|
// Optional base URL of the exchange for looking up wire transfers
|
||||||
// associated with this transaction. If not given,
|
// associated with this transaction. If not given,
|
||||||
|
@ -657,6 +657,7 @@ export interface PlanchetRecord {
|
|||||||
*/
|
*/
|
||||||
coinIdx: number;
|
coinIdx: number;
|
||||||
|
|
||||||
|
|
||||||
planchetStatus: PlanchetStatus;
|
planchetStatus: PlanchetStatus;
|
||||||
|
|
||||||
lastError: TalerErrorDetail | undefined;
|
lastError: TalerErrorDetail | undefined;
|
||||||
@ -671,6 +672,12 @@ export interface PlanchetRecord {
|
|||||||
|
|
||||||
coinEvHash: string;
|
coinEvHash: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Index into the kappa-many planchet commitments per coin
|
||||||
|
* for the age-withdraw operation.
|
||||||
|
*/
|
||||||
|
ageWithdrawIdx?: number;
|
||||||
|
|
||||||
ageCommitmentProof?: AgeCommitmentProof;
|
ageCommitmentProof?: AgeCommitmentProof;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1423,7 +1430,7 @@ export interface KycPendingInfo {
|
|||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* Group of withdrawal operations that need to be executed.
|
* Group of withdrawal operations that need to be executed.
|
||||||
* (Either for a normal withdrawal or from a reward.)
|
* (Either for a normal {single-|batch-|age-} withdrawal or from a reward.)
|
||||||
*
|
*
|
||||||
* The withdrawal group record is only created after we know
|
* The withdrawal group record is only created after we know
|
||||||
* the coin selection we want to withdraw.
|
* the coin selection we want to withdraw.
|
||||||
@ -2513,6 +2520,11 @@ export const WalletStoresV1 = {
|
|||||||
"planchets",
|
"planchets",
|
||||||
describeContents<PlanchetRecord>({ keyPath: "coinPub" }),
|
describeContents<PlanchetRecord>({ keyPath: "coinPub" }),
|
||||||
{
|
{
|
||||||
|
byGroupAgeCoin: describeIndex("byGroupAgeCoin", [
|
||||||
|
"withdrawalGroupId",
|
||||||
|
"ageWithdrawIdx",
|
||||||
|
"coinIdx",
|
||||||
|
]),
|
||||||
byGroupAndIndex: describeIndex("byGroupAndIndex", [
|
byGroupAndIndex: describeIndex("byGroupAndIndex", [
|
||||||
"withdrawalGroupId",
|
"withdrawalGroupId",
|
||||||
"coinIdx",
|
"coinIdx",
|
||||||
|
@ -62,6 +62,10 @@ import {
|
|||||||
ExchangeWithdrawResponse,
|
ExchangeWithdrawResponse,
|
||||||
WithdrawUriInfoResponse,
|
WithdrawUriInfoResponse,
|
||||||
ExchangeBatchWithdrawRequest,
|
ExchangeBatchWithdrawRequest,
|
||||||
|
ExchangeAgeWithdrawRequest,
|
||||||
|
ExchangeAgeWithdrawRevealRequest,
|
||||||
|
ExchangeAgeWithdrawResponse,
|
||||||
|
ExchangeAgeWithdrawRevealResponse,
|
||||||
TransactionState,
|
TransactionState,
|
||||||
TransactionMajorState,
|
TransactionMajorState,
|
||||||
TransactionMinorState,
|
TransactionMinorState,
|
||||||
@ -861,6 +865,7 @@ async function processPlanchetExchangeBatchRequest(
|
|||||||
coinIdx < wgContext.numPlanchets;
|
coinIdx < wgContext.numPlanchets;
|
||||||
coinIdx++
|
coinIdx++
|
||||||
) {
|
) {
|
||||||
|
// FIXME[oec]: Add lookup of planchet for age-withdraw here
|
||||||
let planchet = await tx.planchets.indexes.byGroupAndIndex.get([
|
let planchet = await tx.planchets.indexes.byGroupAndIndex.get([
|
||||||
withdrawalGroup.withdrawalGroupId,
|
withdrawalGroup.withdrawalGroupId,
|
||||||
coinIdx,
|
coinIdx,
|
||||||
@ -923,6 +928,8 @@ async function processPlanchetExchangeBatchRequest(
|
|||||||
|
|
||||||
// FIXME: handle individual error codes better!
|
// FIXME: handle individual error codes better!
|
||||||
|
|
||||||
|
// FIXME[oec]: add age-withdraw-request here
|
||||||
|
|
||||||
if (args.useBatchRequest) {
|
if (args.useBatchRequest) {
|
||||||
const reqUrl = new URL(
|
const reqUrl = new URL(
|
||||||
`reserves/${withdrawalGroup.reservePub}/batch-withdraw`,
|
`reserves/${withdrawalGroup.reservePub}/batch-withdraw`,
|
||||||
|
Loading…
Reference in New Issue
Block a user