Skip to content

Commit 3bc3feb

Browse files
Local ledger implementation in typescript
1 parent 685c0a9 commit 3bc3feb

File tree

4 files changed

+107
-7
lines changed

4 files changed

+107
-7
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ This project adheres to
4545
https://github.com/o1-labs/o1js/pull/2436
4646
- Improved the runtime table API with a `RuntimeTable` class with better
4747
readability https://github.com/o1-labs/o1js/pull/2402
48+
- Internal `Mina.LocalBlockchain` type exported via `Mina`. https://github.com/o1-labs/o1js/pull/2538
4849

4950
### Fixed
5051

src/lib/ledger/ledger.ts

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
import { TokenId, ZkappCommand } from '../mina/v1/account-update.js';
2+
import { Account, newAccount } from '../mina/v1/account.js';
3+
import { NetworkValue } from '../mina/v1/precondition.js';
4+
import { Account as AccountV2 } from '../mina/v2/account.js';
5+
import { InitialApplyState, checkAndApplyAccountUpdate } from '../mina/v2/zkapp-logic.js';
6+
import { PublicKey } from '../provable/crypto/signature.js';
7+
import { UInt64 } from '../provable/int.js';
8+
import { Field } from '../provable/wrapped.js';
9+
export const DefaultTokenId = 1n;
10+
11+
export type AccountId = { publicKey: PublicKey; tokenId?: Field };
12+
13+
export class Ledger {
14+
_nextLocation: bigint;
15+
_accounts: Map<bigint, Account>;
16+
_locations: Map<AccountId, bigint>;
17+
18+
constructor() {
19+
this._nextLocation = 1n;
20+
this._accounts = new Map<bigint, Account>();
21+
this._locations = new Map<AccountId, bigint>();
22+
}
23+
24+
static create(): Ledger {
25+
return new Ledger();
26+
}
27+
28+
addAccount(publicKey: PublicKey, balance: bigint | number | string): void {
29+
const accountId = { publicKey, tokenId: TokenId.default };
30+
const location = (() => {
31+
const existing = this._locations.get(accountId);
32+
if (existing !== undefined) {
33+
throw new Error('account with public key already exists');
34+
}
35+
36+
const newLocation = this._nextLocation;
37+
this._nextLocation += 1n;
38+
39+
return newLocation;
40+
})();
41+
42+
const account = newAccount(accountId);
43+
account.balance = UInt64.from(balance);
44+
45+
this._locations.set(accountId, location);
46+
this._accounts.set(location, account);
47+
}
48+
49+
getAccount(publicKey: PublicKey, tokenId: Field = TokenId.default): Account | undefined {
50+
const accountId = { publicKey, tokenId };
51+
const location = this._locations.get(accountId);
52+
if (location === undefined) {
53+
return undefined;
54+
}
55+
56+
return undefined;
57+
}
58+
59+
applyTransaction(transaction: ZkappCommand, networkState: NetworkValue): void {
60+
for (const update of transaction.accountUpdates) {
61+
const { body, authorization } = update;
62+
63+
if (body.authorizationKind.isProved && !authorization.proof) {
64+
throw Error(
65+
`The actual authorization does not match the expected authorization kind. Did you forget to invoke \`await tx.prove()\`?`
66+
);
67+
}
68+
69+
const accountId: AccountId = { publicKey: body.publicKey, tokenId: body.tokenId };
70+
const account = (() => {
71+
const location = this._locations.get(accountId);
72+
if (location === undefined) {
73+
throw new Error('account not found');
74+
}
75+
76+
return this._accounts.get(location);
77+
})();
78+
if (account === undefined) {
79+
throw new Error('account not found');
80+
}
81+
82+
const accountV2 = AccountV2.fromGeneric(account);
83+
84+
85+
/// WIP here
86+
87+
checkAndApplyAccountUpdate(networkState, accountV2, update, InitialApplyState);
88+
}
89+
}
90+
}

src/lib/mina/v1/local-blockchain.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,11 @@ namespace TestPublicKey {
6161
}
6262
}
6363

64+
<<<<<<< Updated upstream
6465
export type LocalBlockchain = Awaited<ReturnType<typeof LocalBlockchain>>;
66+
=======
67+
export type LocalBlockchain = Awaited<ReturnType<typeof LocalBlockchain>>
68+
>>>>>>> Stashed changes
6569

6670
/**
6771
* A mock Mina blockchain running locally and useful for testing.

src/lib/mina/v2/zkapp-logic.ts

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,33 @@
1+
import { Bool } from '../../provable/bool.js';
2+
import { PublicKey } from '../../provable/crypto/signature.js';
3+
import { Field } from '../../provable/field.js';
4+
import { Int64, Sign, UInt32, UInt64 } from '../../provable/int.js';
5+
import { ZkappConstants } from '../v1/constants.js';
16
import { AccountUpdate } from './account-update.js';
27
import { Account } from './account.js';
38
import { AuthorizationLevel } from './authorization.js';
49
import { Update } from './core.js';
510
import { Permissions } from './permissions.js';
611
import {
7-
Preconditions,
812
EpochDataPreconditions,
913
EpochLedgerPreconditions,
14+
Preconditions,
1015
} from './preconditions.js';
1116
import { StateLayout, StateUpdates, StateValues } from './state.js';
1217
import { ZkappFeePayment } from './transaction.js';
1318
import { ChainView, EpochData, EpochLedgerData } from './views.js';
14-
import { Bool } from '../../provable/bool.js';
15-
import { Field } from '../../provable/field.js';
16-
import { Int64, Sign, UInt64, UInt32 } from '../../provable/int.js';
17-
import { PublicKey } from '../../provable/crypto/signature.js';
18-
import { ZkappConstants } from '../v1/constants.js';
1919

20-
export { checkAndApplyAccountUpdate, checkAndApplyFeePayment, ApplyState };
20+
export { ApplyState, checkAndApplyAccountUpdate, checkAndApplyFeePayment };
2121

2222
type ApplyResult<T> = ({ status: 'Applied' } & T) | { status: 'Failed'; errors: Error[] };
2323

2424
type ApplyState<T> = { status: 'Alive'; value: T } | { status: 'Dead' };
2525

26+
export const InitialApplyState = {
27+
status: 'Alive',
28+
value: Int64.zero,
29+
};
30+
2631
function updateApplyState<T>(
2732
applyState: ApplyState<T>,
2833
errors: Error[],

0 commit comments

Comments
 (0)