Skip to content

Commit

Permalink
feat(besu): add keychain reference signing support
Browse files Browse the repository at this point in the history
Also
1. increases test coverage
2. updates the test contract to have state altering methods

Signed-off-by: Peter Somogyvari <peter.somogyvari@accenture.com>
  • Loading branch information
petermetz committed Dec 1, 2020
1 parent 00b7e62 commit 768c4cc
Show file tree
Hide file tree
Showing 8 changed files with 744 additions and 75 deletions.
1 change: 1 addition & 0 deletions packages/cactus-plugin-ledger-connector-besu/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@
"web3-eea": "0.10.0"
},
"devDependencies": {
"@hyperledger/cactus-plugin-keychain-memory": "^0.2.0",
"@hyperledger/cactus-test-tooling": "0.2.0",
"@types/express": "4.17.8",
"@types/joi": "14.3.4"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,9 @@
{
"$ref": "#/components/schemas/Web3SigningCredentialGethKeychainPassword"
},
{
"$ref": "#/components/schemas/Web3SigningCredentialCactusKeychainRef"
},
{
"$ref": "#/components/schemas/Web3SigningCredentialPrivateKeyHex"
},
Expand Down Expand Up @@ -78,6 +81,39 @@
}
}
},
"Web3SigningCredentialCactusKeychainRef": {
"type": "object",
"required": [
"type",
"ethAccount",
"keychainId",
"keychainEntryKey"
],
"properties": {
"type": {
"$ref": "#/components/schemas/Web3SigningCredentialType"
},
"ethAccount": {
"type": "string",
"description": "The ethereum account (public key) that the credential belongs to. Basically the username in the traditional terminology of authentication.",
"minLength": 64,
"maxLength": 64,
"nullable": false
},
"keychainEntryKey": {
"type": "string",
"description": "The key to use when looking up the the keychain entry holding the secret pointed to by the keychainEntryKey parameter.",
"minLength": 0,
"maxLength": 1024
},
"keychainId": {
"type": "string",
"description": "The keychain ID to use when looking up the the keychain plugin instance that will be used to retrieve the secret pointed to by the keychainEntryKey parameter.",
"minLength": 0,
"maxLength": 1024
}
}
},
"Web3SigningCredentialPrivateKeyHex": {
"type": "object",
"required": [
Expand Down Expand Up @@ -119,6 +155,7 @@
"Web3SigningCredentialType": {
"type": "string",
"enum": [
"CACTUS_KEYCHAIN_REF",
"GETH_KEYCHAIN_PASSWORD",
"PRIVATE_KEY_HEX",
"NONE"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -319,8 +319,39 @@ export interface SolidityContractJsonArtifact {
* @type Web3SigningCredential
* @export
*/
export type Web3SigningCredential = Web3SigningCredentialGethKeychainPassword | Web3SigningCredentialNone | Web3SigningCredentialPrivateKeyHex;
export type Web3SigningCredential = Web3SigningCredentialCactusKeychainRef | Web3SigningCredentialGethKeychainPassword | Web3SigningCredentialNone | Web3SigningCredentialPrivateKeyHex;

/**
*
* @export
* @interface Web3SigningCredentialCactusKeychainRef
*/
export interface Web3SigningCredentialCactusKeychainRef {
/**
*
* @type {Web3SigningCredentialType}
* @memberof Web3SigningCredentialCactusKeychainRef
*/
type: Web3SigningCredentialType;
/**
* The ethereum account (public key) that the credential belongs to. Basically the username in the traditional terminology of authentication.
* @type {string}
* @memberof Web3SigningCredentialCactusKeychainRef
*/
ethAccount: string;
/**
* The key to use when looking up the the keychain entry holding the secret pointed to by the keychainEntryKey parameter.
* @type {string}
* @memberof Web3SigningCredentialCactusKeychainRef
*/
keychainEntryKey: string;
/**
* The keychain ID to use when looking up the the keychain plugin instance that will be used to retrieve the secret pointed to by the keychainEntryKey parameter.
* @type {string}
* @memberof Web3SigningCredentialCactusKeychainRef
*/
keychainId: string;
}
/**
*
* @export
Expand Down Expand Up @@ -390,6 +421,7 @@ export interface Web3SigningCredentialPrivateKeyHex {
* @enum {string}
*/
export enum Web3SigningCredentialType {
CACTUSKEYCHAINREF = 'CACTUS_KEYCHAIN_REF',
GETHKEYCHAINPASSWORD = 'GETH_KEYCHAIN_PASSWORD',
PRIVATEKEYHEX = 'PRIVATE_KEY_HEX',
NONE = 'NONE'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,9 @@ export const CACTUS_OPEN_API_JSON: OpenAPIV3.Document = {
$ref:
"#/components/schemas/Web3SigningCredentialGethKeychainPassword",
},
{
$ref: "#/components/schemas/Web3SigningCredentialCactusKeychainRef",
},
{ $ref: "#/components/schemas/Web3SigningCredentialPrivateKeyHex" },
{ $ref: "#/components/schemas/Web3SigningCredentialNone" },
],
Expand Down Expand Up @@ -76,6 +79,43 @@ export const CACTUS_OPEN_API_JSON: OpenAPIV3.Document = {
},
},
},
Web3SigningCredentialCactusKeychainRef: {
type: "object",
required: ["type", "ethAccount", "keychainId", "keychainEntryKey"],
properties: {
type: {
$ref: "#/components/schemas/Web3SigningCredentialType",
},
ethAccount: {
type: "string",
description:
"The ethereum account (public key) that the credential " +
" belongs to. Basically the username in the traditional " +
" terminology of authentication.",
minLength: 64,
maxLength: 64,
nullable: false,
},
keychainEntryKey: {
type: "string",
description:
"The key to use when looking up the" +
" the keychain entry holding the secret pointed to by the " +
" keychainEntryKey parameter.",
minLength: 0,
maxLength: 1024,
},
keychainId: {
type: "string",
description:
"The keychain ID to use when looking up the" +
" the keychain plugin instance that will be used to retrieve" +
" the secret pointed to by the keychainEntryKey parameter.",
minLength: 0,
maxLength: 1024,
},
},
},
Web3SigningCredentialPrivateKeyHex: {
type: "object",
required: ["type", "ethAccount", "secret"],
Expand Down Expand Up @@ -114,7 +154,12 @@ export const CACTUS_OPEN_API_JSON: OpenAPIV3.Document = {
},
Web3SigningCredentialType: {
type: "string",
enum: ["GETH_KEYCHAIN_PASSWORD", "PRIVATE_KEY_HEX", "NONE"],
enum: [
"CACTUS_KEYCHAIN_REF",
"GETH_KEYCHAIN_PASSWORD",
"PRIVATE_KEY_HEX",
"NONE",
],
},
EthContractInvocationType: {
type: "string",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ import {
PluginAspect,
ICactusPlugin,
ICactusPluginOptions,
PluginRegistry,
IPluginKeychain,
} from "@hyperledger/cactus-core-api";

import {
Expand All @@ -36,6 +38,7 @@ import {
InvokeContractV1Response,
RunTransactionRequest,
RunTransactionResponse,
Web3SigningCredentialCactusKeychainRef,
Web3SigningCredentialGethKeychainPassword,
Web3SigningCredentialPrivateKeyHex,
Web3SigningCredentialType,
Expand All @@ -48,6 +51,7 @@ import { isWeb3SigningCredentialNone } from "./model-type-guards";
export interface IPluginLedgerConnectorBesuOptions
extends ICactusPluginOptions {
rpcApiHttpHost: string;
pluginRegistry: PluginRegistry;
logLevel?: LogLevelDesc;
}

Expand All @@ -64,6 +68,7 @@ export class PluginLedgerConnectorBesu
private readonly instanceId: string;
private readonly log: Logger;
private readonly web3: Web3;
private readonly pluginRegistry: PluginRegistry;
private httpServer: Server | SecureServer | null = null;

public static readonly CLASS_NAME = "PluginLedgerConnectorBesu";
Expand All @@ -77,6 +82,7 @@ export class PluginLedgerConnectorBesu
Checks.truthy(options, `${fnTag} arg options`);
Checks.truthy(options.rpcApiHttpHost, `${fnTag} options.rpcApiHttpHost`);
Checks.truthy(options.instanceId, `${fnTag} options.instanceId`);
Checks.truthy(options.pluginRegistry, `${fnTag} options.pluginRegistry`);

const level = this.options.logLevel || "INFO";
const label = this.className;
Expand All @@ -87,6 +93,7 @@ export class PluginLedgerConnectorBesu
);
this.web3 = new Web3(web3Provider);
this.instanceId = options.instanceId;
this.pluginRegistry = options.pluginRegistry;
}

public getInstanceId(): string {
Expand Down Expand Up @@ -203,6 +210,9 @@ export class PluginLedgerConnectorBesu
const fnTag = `${this.className}#transact()`;

switch (req.web3SigningCredential.type) {
case Web3SigningCredentialType.CACTUSKEYCHAINREF: {
return this.transactCactusKeychainRef(req);
}
case Web3SigningCredentialType.GETHKEYCHAINPASSWORD: {
return this.transactGethKeychain(req);
}
Expand Down Expand Up @@ -290,6 +300,39 @@ export class PluginLedgerConnectorBesu
}
}

public async transactCactusKeychainRef(
req: RunTransactionRequest
): Promise<RunTransactionResponse> {
const fnTag = `${this.className}#transactCactusKeychainRef()`;
const { transactionConfig, web3SigningCredential } = req;
const {
ethAccount,
keychainEntryKey,
keychainId,
} = web3SigningCredential as Web3SigningCredentialCactusKeychainRef;

// locate the keychain plugin that has access to the keychain backend
// denoted by the keychainID from the request.
const keychainPlugin = this.pluginRegistry
.findManyByAspect<IPluginKeychain>(PluginAspect.KEYCHAIN)
.find((k) => k.getKeychainId() === keychainId);

Checks.truthy(keychainPlugin, `${fnTag} keychain for ID:"${keychainId}"`);

// Now use the found keychain plugin to actually perform the lookup of
// the private key that we need to run the transaction.
const privateKeyHex = await keychainPlugin?.get<string>(keychainEntryKey);

return this.transactPrivateKey({
transactionConfig,
web3SigningCredential: {
ethAccount,
type: Web3SigningCredentialType.PRIVATEKEYHEX,
secret: privateKeyHex,
},
});
}

public async pollForTxReceipt(
txHash: string,
timeoutMs: number = 60000
Expand Down

0 comments on commit 768c4cc

Please sign in to comment.