Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve system contract loading reliability #264

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 32 additions & 11 deletions src/accounts/accountManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,14 @@ import * as ecc from 'eosjs-ecc';
import { Account } from './account';
import { accountNameFromPublicKey } from './utils';
import { EOSManager } from '../eosManager';
import { ConfigManager, LamingtonDebugLevel } from '../configManager';
import * as chalk from 'chalk';

interface AccountCreationOptions {
creator?: Account;
eos?: Api;
privateKey?: string;
bytesToBuy?: Number;
}

export class AccountManager {
Expand Down Expand Up @@ -41,20 +45,22 @@ export class AccountManager {
const accounts = [];
if (accountNames) {
for (let accountName of accountNames) {
const privateKey = await ecc.unsafeRandomKey();
const publicKey = await ecc.privateToPublic(privateKey);
const account = new Account(accountName, privateKey);
const resolvedPrivateKey = options?.privateKey ?? (await ecc.unsafeRandomKey());
const publicKey = await ecc.privateToPublic(resolvedPrivateKey);
const account = new Account(accountName, resolvedPrivateKey);
// Publish the new account and store result
await AccountManager.setupAccount(account, options);
accounts.push(account);
}
} else {
// Repeat account creation for specified
for (let i = 0; i < numberOfAccounts; i++) {
const privateKey = await ecc.unsafeRandomKey();
const publicKey = await ecc.privateToPublic(privateKey);
const resolvedPrivateKey = options?.privateKey ?? (await ecc.unsafeRandomKey());

const seedKey = await ecc.unsafeRandomKey();
const publicKey = await ecc.privateToPublic(seedKey);
const accountName = accountNameFromPublicKey(publicKey);
const account = new Account(accountName, privateKey);
const account = new Account(accountName, resolvedPrivateKey);
// Publish the new account and store result
await AccountManager.setupAccount(account, options);
accounts.push(account);
Expand All @@ -72,8 +78,13 @@ export class AccountManager {
* @returns Transaction result promise
*/
static setupAccount = async (account: Account, options?: AccountCreationOptions) => {
let logMessage = `Create account: ${account.name}`;
if (options?.privateKey) {
logMessage += ` private key: ${options.privateKey} `;
}
const { creator, eos } = AccountManager.flattenOptions(options);
// Validate account contains required values

if (!account.name) throw new Error('Missing account name.');
if (!account.publicKey) throw new Error('Missing public key.');
if (!account.privateKey) throw new Error('Missing private key.');
Expand Down Expand Up @@ -122,35 +133,45 @@ export class AccountManager {
// newaccount alone is enough. If there is a system contract with the buyrambytes action,
// then we definitely need to do it, but if there isn't, then trying to call it is an error.
if (systemContract.actions.has('buyrambytes')) {
const bytesToBuy = options?.bytesToBuy ?? 4000000;
logMessage += ` with ram: ${bytesToBuy}`;

actions.push({
account: 'eosio',
name: 'buyrambytes',
authorization: creator.active,
data: {
payer: creator.name,
receiver: account,
bytes: 8192,
receiver: account.name,
bytes: bytesToBuy,
},
});
}
// Same deal for delegatebw. Only if it's actually a thing.
if (systemContract.actions.has('delegatebw')) {
const delegateAmount = '10.0000 EOS';
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

From memory trying to use 10 EOS was breaking with our test chain setup, which is why we were using 10 SYS. Have the later versions of EOS changed this? (e.g. Have you tested that this definitely works? If so, that's all I need, just wanted to check because I remember it causing issues before.)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This worked for me. I was ususally seeing issues where the system contract would not actually get set which is why had delays and retries to get it to work. It also fail silently when it didn't get set which made it even worse to bugfix.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cool, as long as it's working for you I'm good. I think the SYS token is the default if you don't have some of the system contracts set up (which I think you now have set up), so the more we can be like mainnet the better in my opinion. 👍

logMessage += ` bandwidth: ${delegateAmount} for net and cpu`;

actions.push({
account: 'eosio',
name: 'delegatebw',
authorization: creator.active,
data: {
from: creator.name,
receiver: account.name,
stake_net_quantity: '10.0000 SYS',
stake_cpu_quantity: '10.0000 SYS',
stake_net_quantity: delegateAmount,
stake_cpu_quantity: delegateAmount,
transfer: false,
},
});
}
if (ConfigManager.debugLevelMin || ConfigManager.debugLevelVerbose) {
console.log(chalk.cyan(logMessage));
}

// Execute the transaction
return await EOSManager.transact({ actions }, eos, {
logMessage: `Creating account: ${account.name}}`,
logMessage: logMessage,
});
};

Expand Down
8 changes: 1 addition & 7 deletions src/accounts/updateAuth.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { EOSManager } from '../eosManager';
import { Account } from './account';
import { EosioAction } from './utils';

export namespace UpdateAuth {
export interface PermissionLevel {
Expand Down Expand Up @@ -135,10 +136,3 @@ export namespace UpdateAuth {
await EOSManager.transact({ actions });
}
}

export type EosioAction = {
account: string;
name: string;
authorization: { actor: string; permission: string }[];
data: any;
};
7 changes: 7 additions & 0 deletions src/accounts/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,10 @@ export const hashToEOSName = (data: string) =>
.substring(0, 11)
.replace(digitPattern, match => digitMapping[match])
.toLowerCase()}`;

export type EosioAction = {
account: string;
name: string;
authorization: { actor: string; permission: string }[];
data: any;
};
3 changes: 3 additions & 0 deletions src/cli/lamington-test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { eosIsReady, startEos, runTests, stopContainer, buildAll } from './utils';
import { GitIgnoreManager } from '../gitignoreManager';
import { ConfigManager } from '../configManager';
import { sleep } from '../utils';

/**
* Executes a build and test procedure
Expand All @@ -25,6 +26,8 @@ const run = async () => {
// Start compiling smart contracts
if (!args.includes('skip-build')) {
await buildAll();
} else {
await sleep(4000);
}
// Begin running tests
await runTests();
Expand Down
1 change: 1 addition & 0 deletions src/contracts/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@ export * from './contractDeployer';
export * from './contractLoader';
export * from './tableRowsResult';
export * from './typeGenerator';
export * from './typeMap';
Loading