-
Notifications
You must be signed in to change notification settings - Fork 2
/
balanceproof.ts
143 lines (124 loc) · 3.3 KB
/
balanceproof.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
// SPDX-License-Identifier: Apache-2.0
"use strict";
import { ethers, Signer, utils } from "ethers";
import {
TypedJSON,
jsonObject,
jsonMember,
jsonBigIntMember,
} from "#erdstall/export/typedjson";
import { customJSON, ABIPacked, ABIEncoder } from "#erdstall/api/util";
import { Assets } from "#erdstall/ledger/assets";
import { Address } from "#erdstall/ledger";
import { Signature } from "#erdstall/api";
import { ErdstallObject, registerErdstallType } from "#erdstall/api";
const balanceProofsTypeName = "BalanceProofs";
// Balance is the value of funds for the account within epoch.
@jsonObject
export class Balance {
@jsonBigIntMember() epoch: bigint;
@jsonMember(Address) account: Address;
@jsonMember(Boolean) exit: boolean;
@jsonMember(() => Assets) values: Assets;
constructor(
epoch: bigint,
account: Address | string,
exit: boolean,
values: Assets,
) {
this.epoch = epoch;
this.account = Address.ensure(account);
this.exit = exit;
this.values = values;
}
// (uint64,address,bool,tuple(address,bytes)[])
asABI(): ErdstallBalance {
return {
epoch: this.epoch.valueOf(),
account: this.account.toString(),
exit: this.exit,
tokens: this.values.asABI(),
};
}
packTagged(contract: Address): ABIPacked {
return new ABIEncoder(
["uint64", this.epoch],
this.account,
this.exit,
this.values,
).pack("ErdstallBalance", contract);
}
async sign(contract: Address, signer: Signer): Promise<BalanceProof> {
const sig = await signer.signMessage(
this.packTagged(contract).keccak256(),
);
return new BalanceProof(this, new Signature(sig));
}
}
export interface ErdstallBalance {
epoch: ethers.BigNumberish;
account: string;
exit: boolean;
tokens: ErdstallToken[];
}
export interface ErdstallToken {
token: string;
value: ethers.utils.BytesLike;
}
export type ErdstallSignature = ethers.utils.BytesLike;
// A BalanceProof is generated by the Enclave at the end of each transaction
// phase for each account in the Erdstall system.
@jsonObject
export class BalanceProof {
@jsonMember(Balance)
readonly balance: Balance;
@jsonMember(Signature)
readonly sig: Signature;
constructor(balance: Balance, signature: Signature) {
this.balance = balance;
this.sig = signature;
}
toEthProof(): [ErdstallBalance, ErdstallSignature] {
return [this.balance.asABI(), this.sig.value];
}
verify(contract: Address, tee: Address): boolean {
const signer = utils.verifyMessage(
this.balance.packTagged(contract).keccak256(),
this.sig.toString(),
);
return signer === tee.toString();
}
}
@jsonObject
export class BalanceProofs extends ErdstallObject {
public map: Map<string, BalanceProof>;
constructor() {
super();
this.map = new Map<string, BalanceProof>();
}
static toJSON(me: BalanceProofs): any {
var obj: any = {};
me.map.forEach((bp, addr) => {
obj[addr] = JSON.parse(TypedJSON.stringify(bp, BalanceProof));
});
return obj;
}
static fromJSON(data: any): BalanceProofs {
const bps = new BalanceProofs();
for (const addr in data) {
bps.map.set(
addr,
TypedJSON.parse(JSON.stringify(data[addr]), BalanceProof)!,
);
}
return bps;
}
public objectType() {
return BalanceProofs;
}
protected objectTypeName() {
return balanceProofsTypeName;
}
}
registerErdstallType(balanceProofsTypeName, BalanceProofs);
customJSON(BalanceProofs);