Skip to content
This repository has been archived by the owner on May 16, 2024. It is now read-only.

Commit

Permalink
Implement Grade Of Finality Support
Browse files Browse the repository at this point in the history
  • Loading branch information
GalRogozinski committed Nov 2, 2021
1 parent 3d37fa1 commit 275b05f
Show file tree
Hide file tree
Showing 10 changed files with 65 additions and 48 deletions.
32 changes: 31 additions & 1 deletion src/app/components/Settings.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,10 +42,22 @@ class Settings extends Component<SettingsProps, SettingsState> {
password: settings.password,
accessManaPledgeID: settings.accessManaPledgeID,
consensusManaPledgeID: settings.consensusManaPledgeID,
gofConfThreshold: settings.gofConfThreshold,
isBusy: false
});
}

private static imposeMinMax(el: HTMLInputElement): void {
if (el.value !== "") {
if (parseInt(el.value) < parseInt(el.min)) {
el.value = el.min;
}
if (parseInt(el.value) > parseInt(el.max)) {
el.value = el.max;
}
}
}

/**
* Render the component.
* @returns The node to render.
Expand Down Expand Up @@ -139,6 +151,23 @@ class Settings extends Component<SettingsProps, SettingsState> {
onChange={e => this.setState({ consensusManaPledgeID: e.target.value })}
/>
</div>
<div className="card--label">
Grade Of Finality for confirmation
</div>
<div className="card--value">
<input
className="fill"
type="number"
min="1"
max="3"
value={this.state.gofConfThreshold}
onChange={e => {
Settings.imposeMinMax(e.target);
this.setState({ gofConfThreshold: e.target.valueAsNumber });
}
}
/>
</div>
<div className="margin-t-s">
<button
onClick={() => this.save()}
Expand Down Expand Up @@ -178,7 +207,8 @@ class Settings extends Component<SettingsProps, SettingsState> {
user: this.state.user ?? "",
password: this.state.password ?? "",
accessManaPledgeID: this.state.accessManaPledgeID ?? "",
consensusManaPledgeID: this.state.consensusManaPledgeID ?? ""
consensusManaPledgeID: this.state.consensusManaPledgeID ?? "",
gofConfThreshold: this.state.gofConfThreshold ?? 0
};
await this._settingsService.set(newSettings);

Expand Down
5 changes: 5 additions & 0 deletions src/app/components/SettingsState.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,4 +40,9 @@ export interface SettingsState {
* The nodeID of the consensus Mana pledge.
*/
consensusManaPledgeID?: string;

/**
* The minimal grade of finality needed for an output to be confirmed
*/
gofConfThreshold?: number
}
4 changes: 0 additions & 4 deletions src/app/components/Wallet.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -255,7 +255,6 @@ class Wallet extends Component<WalletProps, WalletState> {
<th>Color</th>
<th>Confirmed</th>
<th>Pending</th>
<th>Rejected</th>
<th>&nbsp;</th>
</tr>
</thead>
Expand Down Expand Up @@ -283,9 +282,6 @@ class Wallet extends Component<WalletProps, WalletState> {
<td className="warning">
{balance.unConfirmed.toString()}
</td>
<td className="danger">
{balance.rejected.toString()}
</td>
<td>
<button
disabled={balance.confirmed <= 0}
Expand Down
18 changes: 3 additions & 15 deletions src/iota/api/models/IUnspentOutputsResponse.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,22 +49,10 @@ export interface IUnspentOutputsResponse extends IResponse {
};

/**
* InclusionState represents the different states of an OutputID.
* GradeOfFinality represents the confirmation level. 0 is not confirmed.
* 3 is the maximum confirmation level.
*/
inclusionState: {
/**
* Is the output confirmed.
*/
confirmed?: boolean;
/**
* Is the output rejected.
*/
rejected?: boolean;
/**
* Is the output conflicting.
*/
conflicting?: boolean;
};
gradeOfFinality: number;
}[];
}[];
}
5 changes: 5 additions & 0 deletions src/models/ISettings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,4 +28,9 @@ export interface ISettings {
* Access Mana Pledge ID.
*/
consensusManaPledgeID: string;

/**
* Grade of Finality Confirmation threshold
*/
gofConfThreshold: number;
}
5 changes: 0 additions & 5 deletions src/models/IWalletBalance.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,4 @@ export interface IWalletBalance {
* Unconfirmed Balance.
*/
unConfirmed: bigint;

/**
* Rejected Balance.
*/
rejected: bigint;
}
4 changes: 2 additions & 2 deletions src/models/IWalletOutput.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ export interface IWalletOutput {
balances: IWalletOutputBalance[];

/**
* Inclusion state.
* Grade of finality.
*/
inclusionState: IWalletOutputInclusionState;
gof: number;
}
6 changes: 1 addition & 5 deletions src/models/IWalletOutputInclusionState.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,7 @@ export interface IWalletOutputInclusionState {
/**
* Is the output confirmed.
*/
confirmed?: boolean;
/**
* Is the output rejected.
*/
rejected?: boolean;
gof?: number;
/**
* Is the output liked.
*/
Expand Down
5 changes: 4 additions & 1 deletion src/services/settingsService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ import { ISettings } from "../models/ISettings";
import { IJsonStorageService } from "../models/services/IJsonStorageService";
import { ISettingsService } from "../models/services/ISettingsService";

const defaultGofConfThreshold = 3;

/**
* Service to manage settings.
*/
Expand Down Expand Up @@ -40,7 +42,8 @@ export class SettingsService implements ISettingsService {
user: "",
password: "",
accessManaPledgeID: "",
consensusManaPledgeID: ""
consensusManaPledgeID: "",
gofConfThreshold: defaultGofConfThreshold
};
}

Expand Down
29 changes: 14 additions & 15 deletions src/services/walletService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -358,10 +358,10 @@ export class WalletService implements IWalletService {

const version = 0;
const time = Date.now();
const timestamp = BigInt(time * 1000000);
const timestamp = BigInt(time * 1_000_000);

// Calculate the spending requirements
const consumedOutputs = this.determineOutputsToConsume(sendFundsOptions);
const consumedOutputs = this.determineOutputsToConsume(sendFundsOptions, settings.gofConfThreshold);

const { inputs, consumedFunds } = this.buildInputs(consumedOutputs);
const outputs = this.buildOutputs(sendFundsOptions, consumedFunds);
Expand Down Expand Up @@ -575,7 +575,7 @@ export class WalletService implements IWalletService {
outputs: uo.outputs.filter(o => o.output.type === "SigLockedColoredOutputType").map(uid => ({
id: uid.output.outputID.base58,
balances: this.mapToArray(uid.output.output.balances),
inclusionState: uid.inclusionState
gof: uid.gradeOfFinality
}))
})));
} while (spentAddresses.length > BLOCK_COUNT - 2);
Expand Down Expand Up @@ -607,10 +607,11 @@ export class WalletService implements IWalletService {

/**
* From all the inputs determine which ones we need to consume.
* @param sendFundOptions The request funds.
* @param sendFundOptions The request funds options.
* @param gofConfThreshold the grade of finality needed to consider the outputs as approved
* @returns The output that we need to consume.
*/
private determineOutputsToConsume(sendFundOptions: ISendFundsOptions): {
private determineOutputsToConsume(sendFundOptions: ISendFundsOptions, gofConfThreshold : number): {
[address: string]: { [outputID: string]: IWalletOutput };
} {
const outputsToConsume: { [address: string]: { [outputID: string]: IWalletOutput } } = {};
Expand All @@ -637,9 +638,7 @@ export class WalletService implements IWalletService {
const confirmedUnspentOutputs = unspentOutput.outputs.filter(o =>
(!this._spentOutputTransactions ||
!this._spentOutputTransactions.includes(o.id)) &&
o.inclusionState.confirmed);


o.gof >= gofConfThreshold);
// scan the outputs on this address for required funds
for (const output of confirmedUnspentOutputs) {
// keeps track if the output contains any usable funds
Expand Down Expand Up @@ -895,14 +894,16 @@ export class WalletService implements IWalletService {
const assetsMap: { [id: string]: IWalletAsset } = {};
const addedAssets: IWalletAsset[] = [];
const apiRegistryClient = await this.buildApiRegistryClient();
const settingsService = ServiceFactory.get<SettingsService>("settings");
const settings = await settingsService.get();

for (let i = 0; i <= this._wallet.lastAddressIndex; i++) {
const addr = Seed.generateAddress(Base58.decode(this._wallet.seed), BigInt(i));
const address: IWalletAddress = {
index: BigInt(i),
address: addr,
isSpent: this._wallet &&
this._wallet.spentAddresses.includes(addr) ? true : false
this._wallet.spentAddresses.includes(addr) ? true : false
};
addressMap[address.address] = address;
this._addresses.push(address);
Expand Down Expand Up @@ -948,15 +949,13 @@ export class WalletService implements IWalletService {
colorMap[balance.color] = {
asset: assetsMap[balance.color],
confirmed: BigInt(0),
unConfirmed: BigInt(0),
rejected: BigInt(0)
unConfirmed: BigInt(0)
};
this._balances.push(colorMap[balance.color]);
}
if (output.inclusionState.confirmed) {

if (output.gof >= settings.gofConfThreshold) {
colorMap[balance.color].confirmed += balance.value;
} else if (output.inclusionState.rejected) {
colorMap[balance.color].rejected += balance.value;
} else {
colorMap[balance.color].unConfirmed += balance.value;
}
Expand Down Expand Up @@ -1040,4 +1039,4 @@ export class WalletService implements IWalletService {
const settings = await settingsService.get();
return new ApiRegistryClient(settings.apiRegistryEndpoint);
}
}
}

0 comments on commit 275b05f

Please sign in to comment.