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

feat(cactus-plugin-ledger-connector-ethereum): add signing utils #2750

Merged
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
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ export class BusinessLogicElectricityTrade extends BusinessLogicBase {
{
to: accountInfo["toAddress"],
value: Number(transactionSubset["Value"]),
gas: config.electricityTradeInfo.ethereum.gas,
gasLimit: config.electricityTradeInfo.ethereum.gas,
},
accountInfo["fromAddress"],
accountInfo["fromAddressPkey"],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@
* transaction-ethereum.ts
*/

import { ConfigUtil } from "@hyperledger/cactus-cmd-socketio-server";
import {
ConfigUtil,
TransactionSigner,
} from "@hyperledger/cactus-cmd-socketio-server";
import { Web3SigningCredentialType } from "@hyperledger/cactus-plugin-ledger-connector-ethereum";
Web3SigningCredentialType,
signTransaction,
} from "@hyperledger/cactus-plugin-ledger-connector-ethereum";

const config: any = ConfigUtil.getConfig();
import { getLogger } from "log4js";
Expand Down Expand Up @@ -37,9 +37,15 @@ export async function sendEthereumTransaction(
}
logger.debug("sendEthereumTransaction", transaction);

const { serializedTx, txId } = TransactionSigner.signTxEthereum(
const { serializedTransactionHex, txId } = signTransaction(
transaction,
privateKey,
{
name: config.signTxInfo.ethereum.chainName,
chainId: config.signTxInfo.ethereum.chainID,
networkId: config.signTxInfo.ethereum.networkID,
defaultHardfork: config.signTxInfo.ethereum.defaultHardfork,
},
);
logger.info("Sending ethereum transaction with ID", txId);

Expand All @@ -48,7 +54,7 @@ export async function sendEthereumTransaction(
type: Web3SigningCredentialType.None,
},
transactionConfig: {
rawTransaction: serializedTx,
rawTransaction: serializedTransactionHex,
},
});
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,13 @@ blpRegistry:

logLevel: debug

signTxInfo:
ethereum:
chainName: geth1
networkID: 10
chainID: 10
defaultHardfork: petersburg

appRouters:
-
path: /api/v1/bl/electricity-trade/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,3 @@ ledgerPluginInfo:
ledgerInfo:
ledgerAbstract: Sawtooth Ledger
apiInfo: []

signTxInfo:
ethereum:
chainName: geth1
networkID: 10
chainID: 10
network: mainnet
hardfork: petersburg
68 changes: 68 additions & 0 deletions packages/cactus-plugin-ledger-connector-ethereum/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,74 @@ args: {
},
```

### Offline signing utils
- Use `signTransaction` from this package to sign transactions payload locally (outside of connector process).
- Offline signed transaction can be send with `Web3SigningCredentialType.None` signing credetnial type in runTransactionV1 endpoint.

``` typescript
// Offline sign transaction
const { serializedTransactionHex } = signTransaction(
{
to: anotherAccount,
value: 10e6,
maxPriorityFeePerGas: 0,
maxFeePerGas: 0x40000000,
gasLimit: 21000,
type: 2
},
myPrivateKey,
{
networkId: 10,
chainId: 10,
defaultHardfork: "london",
},
);

// Send transaction payload to connector
await apiClient.runTransactionV1({
web3SigningCredential: {
type: Web3SigningCredentialType.None,
},
transactionConfig: {
rawTransaction: serializedTransactionHex,
},
});
```

### Offline signing utils
- Use `signTransaction` from this package to sign transactions payload locally (outside of connector process).
- Offline signed transaction can be send with `Web3SigningCredentialType.None` signing credetnial type in runTransactionV1 endpoint.

``` typescript
// Offline sign transaction
const { serializedTransactionHex } = signTransaction(
{
to: anotherAccount,
value: 10e6,
maxPriorityFeePerGas: 0,
maxFeePerGas: 0x40000000,
gasLimit: 21000,
type: 2
},
myPrivateKey,
{
networkId: 10,
chainId: 10,
defaultHardfork: "london",
},
);

// Send transaction payload to connector
await apiClient.runTransactionV1({
web3SigningCredential: {
type: Web3SigningCredentialType.None,
},
transactionConfig: {
rawTransaction: serializedTransactionHex,
},
});
```

## JSON-RPC Proxy
- Connector can be used with web3js to send any JSON-RPC request to the ethereum node.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,8 @@
"webpack:dev:web": "webpack --env=dev --target=web --config ../../webpack.config.js"
},
"dependencies": {
"@ethereumjs/common": "4.0.0",
"@ethereumjs/tx": "5.0.0",
"@hyperledger/cactus-common": "2.0.0-alpha.2",
"@hyperledger/cactus-core": "2.0.0-alpha.2",
"@hyperledger/cactus-core-api": "2.0.0-alpha.2",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ export {
IPluginLedgerConnectorEthereumOptions,
} from "./plugin-ledger-connector-ethereum";

export * from "./sign-utils";

export * from "./types/model-type-guards";

export { PluginFactoryLedgerConnector } from "./plugin-factory-ledger-connector";
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import { Chain, Common } from "@ethereumjs/common";
import {
AccessListEIP2930Transaction,
BlobEIP4844Transaction,
FeeMarketEIP1559Transaction,
LegacyTransaction,
TransactionFactory,
TypedTxData,
} from "@ethereumjs/tx";

type CustomChainArg = Parameters<typeof Common.custom>[0];

/**
* Sign ethereum transaction data offline. Can be used with both mainnet and custom chains.
*
* @param txData transaction data (format must be compatible with @ethereumjs/tx)
* @param privateKey HEX private signing key
* @param customChainInfo optional custom chain information (default: mainnet)
*
* @returns serialized transaction, txId (hash) and signedTransaction object
*/
export function signTransaction(
txData: TypedTxData,
privateKey: string,
customChainInfo?: CustomChainArg,
): {
serializedTransactionHex: string;
txId: string;
signedTransactionObject:
| LegacyTransaction
| AccessListEIP2930Transaction
| FeeMarketEIP1559Transaction
| BlobEIP4844Transaction;
} {
let chainConfiguration = new Common({ chain: Chain.Mainnet });
if (customChainInfo) {
chainConfiguration = Common.custom(customChainInfo);
}

const transaction = TransactionFactory.fromTxData(txData, {
common: chainConfiguration,
});
if (privateKey.toLowerCase().startsWith("0x")) {
privateKey = privateKey.slice(2);
}
const signedTransaction = transaction.sign(Buffer.from(privateKey, "hex"));

const hash = signedTransaction.hash();
const txId = "0x" + Buffer.from(hash).toString("hex");
const serializedTransaction = signedTransaction.serialize();
const serializedTransactionHex =
"0x" + Buffer.from(serializedTransaction).toString("hex");

return {
serializedTransactionHex,
txId,
signedTransactionObject: signedTransaction,
};
}
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ import {
InvokeContractV1Request,
DeployContractV1Request,
ContractKeychainDefinition,
signTransaction,
} from "../../../main/typescript/public-api";
import { K_CACTI_ETHEREUM_TOTAL_TX_COUNT } from "../../../main/typescript/prometheus-exporter/metrics";

Expand Down Expand Up @@ -348,13 +349,12 @@ describe("Ethereum contract deploy and invoke using keychain tests", () => {
expect(invokeGetNameOut.data.callOutput).toBe(newName);
});

test("invoke Web3SigningCredentialType.NONE", async () => {
test("invoke Web3SigningCredentialType.None", async () => {
const testEthAccount2 = web3.eth.accounts.create();

const value = 10e6;
const { rawTransaction } = await web3.eth.accounts.signTransaction(
const { serializedTransactionHex } = signTransaction(
{
from: testEthAccount.address,
to: testEthAccount2.address,
value,
maxPriorityFeePerGas: 0,
Expand All @@ -363,14 +363,19 @@ describe("Ethereum contract deploy and invoke using keychain tests", () => {
type: 2,
},
testEthAccount.privateKey,
{
networkId: 10,
chainId: 10,
defaultHardfork: "london",
},
);

await apiClient.runTransactionV1({
web3SigningCredential: {
type: Web3SigningCredentialType.None,
},
transactionConfig: {
rawTransaction,
rawTransaction: serializedTransactionHex,
},
});

Expand Down
65 changes: 65 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -4335,6 +4335,16 @@ __metadata:
languageName: node
linkType: hard

"@ethereumjs/common@npm:4.0.0, @ethereumjs/common@npm:^4.0.0":
version: 4.0.0
resolution: "@ethereumjs/common@npm:4.0.0"
dependencies:
"@ethereumjs/util": ^9.0.0
crc: ^4.3.2
checksum: 3fa2f6a55ff5a2406241fc1ffbdc6f60cfa139edaf9afac2164d25ca35e31a0d2901de40a517f42e5a466aab316f9187c5b787f33f3260e746b13209c910c67f
languageName: node
linkType: hard

"@ethereumjs/common@npm:^2.3.0, @ethereumjs/common@npm:^2.4.0, @ethereumjs/common@npm:^2.6.1":
version: 2.6.2
resolution: "@ethereumjs/common@npm:2.6.2"
Expand Down Expand Up @@ -4374,6 +4384,15 @@ __metadata:
languageName: node
linkType: hard

"@ethereumjs/rlp@npm:^5.0.0":
version: 5.0.0
resolution: "@ethereumjs/rlp@npm:5.0.0"
bin:
rlp: bin/rlp
checksum: 86d42f88945f25fc2874f80efc4d4c37cc85fc375920134392b658c0140346fb22b815e73680b87d1fea3ae55ad6ca42ea9fec7150583be496577b01bffb9e58
languageName: node
linkType: hard

"@ethereumjs/tx@npm:3.3.2":
version: 3.3.2
resolution: "@ethereumjs/tx@npm:3.3.2"
Expand All @@ -4384,6 +4403,23 @@ __metadata:
languageName: node
linkType: hard

"@ethereumjs/tx@npm:5.0.0":
version: 5.0.0
resolution: "@ethereumjs/tx@npm:5.0.0"
dependencies:
"@ethereumjs/common": ^4.0.0
"@ethereumjs/rlp": ^5.0.0
"@ethereumjs/util": ^9.0.0
ethereum-cryptography: ^2.1.2
peerDependencies:
c-kzg: ^2.1.0
peerDependenciesMeta:
c-kzg:
optional: true
checksum: 1f642781cca8251fb036ef9b77e95c8e3e8e7b1996d295e01f9875a581ccf25fa38eea270d032a8ab4cb1b6d716b50496b7400ccc37875b896912e6fd0300de8
languageName: node
linkType: hard

"@ethereumjs/tx@npm:^3.2.1":
version: 3.5.0
resolution: "@ethereumjs/tx@npm:3.5.0"
Expand Down Expand Up @@ -4415,6 +4451,21 @@ __metadata:
languageName: node
linkType: hard

"@ethereumjs/util@npm:^9.0.0":
version: 9.0.0
resolution: "@ethereumjs/util@npm:9.0.0"
dependencies:
"@ethereumjs/rlp": ^5.0.0
ethereum-cryptography: ^2.1.2
peerDependencies:
c-kzg: ^2.1.0
peerDependenciesMeta:
c-kzg:
optional: true
checksum: c0e2a50aac614a8167df060f0fe6d7b9805adebd83df81a26b596c92eb76454e2e6f25d8f5b9e49cb629355020a8a07feb4d6c1b8238990dcf82e256153bf328
languageName: node
linkType: hard

"@ethersproject/abi@npm:5.0.7":
version: 5.0.7
resolution: "@ethersproject/abi@npm:5.0.7"
Expand Down Expand Up @@ -6475,6 +6526,8 @@ __metadata:
version: 0.0.0-use.local
resolution: "@hyperledger/cactus-plugin-ledger-connector-ethereum@workspace:packages/cactus-plugin-ledger-connector-ethereum"
dependencies:
"@ethereumjs/common": 4.0.0
"@ethereumjs/tx": 5.0.0
"@hyperledger/cactus-common": 2.0.0-alpha.2
"@hyperledger/cactus-core": 2.0.0-alpha.2
"@hyperledger/cactus-core-api": 2.0.0-alpha.2
Expand Down Expand Up @@ -17341,6 +17394,18 @@ __metadata:
languageName: node
linkType: hard

"crc@npm:^4.3.2":
version: 4.3.2
resolution: "crc@npm:4.3.2"
peerDependencies:
buffer: ">=6.0.3"
peerDependenciesMeta:
buffer:
optional: true
checksum: 8231cc25331727083ffd22da3575110fc49b4dc8725de973bd43261d4426aba134ed3a75cc247f7c5e97a6e171f87dffc3325b82890e86d032de2e6bcef09c32
languageName: node
linkType: hard

"create-ecdh@npm:^4.0.0":
version: 4.0.4
resolution: "create-ecdh@npm:4.0.4"
Expand Down
Loading