forked from RafaelAPB/blockchain-integration-framework
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(bungee): Refactoring bungee plugin
- Loading branch information
Showing
25 changed files
with
6,352 additions
and
827 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
241 changes: 241 additions & 0 deletions
241
packages/cactus-plugin-bungee/src/main/typescript/besu-bungee.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,241 @@ | ||
import { Configuration } from "@hyperledger/cactus-core-api"; | ||
import { | ||
DefaultApi as BesuApi, | ||
EthContractInvocationType, | ||
EvmBlock, | ||
EvmLog, | ||
GetBlockV1Request, | ||
GetPastLogsV1Request, | ||
GetTransactionV1Request, | ||
InvokeContractV1Request, | ||
Web3SigningCredential, | ||
} from "@hyperledger/cactus-plugin-ledger-connector-besu"; | ||
import { State } from "./view-creation/state"; | ||
import Web3 from "web3"; | ||
import { Transaction } from "./view-creation/transaction"; | ||
import { Proof } from "./view-creation/proof"; | ||
import { IPluginBUNGEEOptions, PluginBUNGEE } from "./plugin-bungee"; | ||
import { StateProof } from "./view-creation/state-proof"; | ||
import { TransactionProof } from "./view-creation/transaction-proof"; | ||
/* | ||
enum Consensus { | ||
qbft = "QBFT", | ||
ibft = "IBFT", | ||
clique = "CLIQUE", | ||
pow = "PoW", | ||
}*/ | ||
export interface IKeyPair { | ||
publicKey: Uint8Array; | ||
privateKey: Uint8Array; | ||
} | ||
|
||
export interface IPluginBUNGEEBesuOptions extends IPluginBUNGEEOptions { | ||
besuPath?: string; | ||
besuSigningCredential?: Web3SigningCredential; | ||
bungeeContractAddress?: string; | ||
besuContractName?: string; | ||
keychainId?: string; | ||
//besuConfig?: Configuration; | ||
besuApi?: BesuApi; | ||
} | ||
|
||
export class BesuBUNGEE extends PluginBUNGEE { | ||
public besuApi?: BesuApi; | ||
public besuSigningCredential?: Web3SigningCredential; | ||
public besuChannelName?: string; | ||
public besuContractName?: string; | ||
public besuAssetID?: string; | ||
public besuAssetSize?: string; | ||
private bungeeContractAddress?: string; | ||
private keychainId?: string; | ||
|
||
constructor(public readonly options: IPluginBUNGEEBesuOptions) { | ||
super({ | ||
instanceId: options.instanceId, | ||
participant: options.participant, | ||
keyPair: options.keyPair, | ||
logLevel: options.logLevel, | ||
disableSignalHandlers: options.disableSignalHandlers, | ||
}); | ||
this.besuApi = options.besuApi; | ||
if (options.besuPath != undefined) this.defineBesuConnection(options); | ||
} | ||
|
||
private defineBesuConnection(options: IPluginBUNGEEBesuOptions): void { | ||
this.logger.info(`OPTIONS:: ${options}`); | ||
const fnTag = `${this.className}#defineFabricConnection()`; | ||
|
||
const config = new Configuration({ basePath: options.besuPath }); | ||
const apiClient = new BesuApi(config); | ||
this.besuApi = apiClient; | ||
const notEnoughBesuParams: boolean = | ||
options.besuSigningCredential == undefined || | ||
options.besuContractName == undefined || | ||
options.bungeeContractAddress == undefined || | ||
options.keychainId == undefined; | ||
if (notEnoughBesuParams) { | ||
throw new Error( | ||
`${fnTag}, besu params missing should have: signing credentials, contract name`, | ||
); | ||
} | ||
this.besuSigningCredential = options.besuSigningCredential; | ||
this.bungeeContractAddress = options.bungeeContractAddress; | ||
this.besuContractName = options.besuContractName; | ||
this.keychainId = options.keychainId; | ||
} | ||
|
||
public async generateLedgerStates() { | ||
this.logger.debug(`Generating ledger snapshot`); | ||
|
||
const assetsKey = (await this.getAllAssetsKey()) as string[]; | ||
this.logger.debug("Current assets detected to capture: " + assetsKey); | ||
for (const assetKey of assetsKey) { | ||
const { transactions, values, blocks } = | ||
await this.getAllInfoByKey(assetKey); | ||
|
||
//========= | ||
// query last value, or get all from logs? | ||
/*const value = await this.besuApi?.invokeContractV1({ | ||
contractName: this.besuContractName, | ||
keychainId: this.keychainId, | ||
invocationType: EthContractInvocationType.Call, | ||
methodName: "getAsset", | ||
params: [assetKey], | ||
signingCredential: this.besuSigningCredential, | ||
gas: 1000000, | ||
} as InvokeContractV1Request);*/ | ||
//========= | ||
|
||
const state = new State(assetKey, values, transactions); | ||
|
||
const stateProof = new StateProof( | ||
state.getValue(), | ||
parseInt(state.getVersion()), | ||
state.getId(), | ||
); | ||
const blocksHash: string[] = []; | ||
for (const block of blocks.values()) { | ||
if (blocksHash.indexOf(block.hash as string) !== -1) { | ||
continue; | ||
} | ||
blocksHash.push(block.hash as string); | ||
stateProof.addBlock({ | ||
blockHash: block.hash as string, | ||
blockCreator: block.miner as string, | ||
blockSigners: [], // FIXME: query blocksigners (blockchain specific) | ||
}); | ||
} | ||
state.setStateProof([]); | ||
this.ledgerStates.set(assetKey, state); | ||
this.states.push(state); | ||
} | ||
} | ||
|
||
async getAllAssetsKey(): Promise<string | string[]> { | ||
const parameters = { | ||
contractName: this.besuContractName, | ||
keychainId: this.keychainId, | ||
invocationType: EthContractInvocationType.Call, | ||
methodName: "getAllAssetsIDs", | ||
params: [], | ||
signingCredential: this.besuSigningCredential, | ||
gas: 1000000, | ||
}; | ||
const response = await this.besuApi?.invokeContractV1( | ||
parameters as InvokeContractV1Request, | ||
); | ||
if (response != undefined) { | ||
return response.data.callOutput; | ||
} | ||
|
||
return "response undefined"; | ||
} | ||
|
||
async getAllInfoByKey(key: string): Promise<{ | ||
transactions: Transaction[]; | ||
values: string[]; | ||
blocks: Map<string, EvmBlock>; | ||
}> { | ||
const req = { | ||
address: this.bungeeContractAddress, | ||
topics: [[null], [Web3.utils.keccak256(key)]], | ||
}; | ||
const response = await this.besuApi?.getPastLogsV1( | ||
req as GetPastLogsV1Request, | ||
); | ||
if (response == undefined) { | ||
return { | ||
transactions: [], | ||
values: [], | ||
blocks: new Map<string, EvmBlock>(), | ||
}; | ||
} | ||
const decoded = response.data.logs as EvmLog[]; | ||
const transactions: Transaction[] = []; | ||
const blocks: Map<string, EvmBlock> = new Map<string, EvmBlock>(); | ||
const values: string[] = []; | ||
this.logger.debug("Getting transaction logs for asset: " + key); | ||
|
||
for (const log of decoded) { | ||
const txTx = await this.besuApi?.getTransactionV1({ | ||
transactionHash: log.transactionHash, | ||
} as GetTransactionV1Request); | ||
|
||
const txBlock = await this.besuApi?.getBlockV1({ | ||
blockHashOrBlockNumber: log.blockHash, | ||
} as GetBlockV1Request); | ||
if (txTx == undefined || txBlock == undefined) { | ||
this.logger.debug( | ||
"some error occurred fetching transaction or block info in ", | ||
); | ||
return { | ||
transactions: [], | ||
values: [], | ||
blocks: new Map<string, EvmBlock>(), | ||
}; | ||
} | ||
this.logger.debug( | ||
"Transaction: " + | ||
log.transactionHash + | ||
"\nData: " + | ||
JSON.stringify(this.splitDataIntoChunks(log.data)) + | ||
"\n =========== \n", | ||
); | ||
const proof = new Proof({ | ||
creator: txTx.data.transaction.from as string, //no proof for bungee | ||
}); | ||
const transaction: Transaction = new Transaction( | ||
log.transactionHash, | ||
txBlock.data.block.timestamp, | ||
new TransactionProof(proof), | ||
); | ||
transaction.setStateId(key); | ||
transaction.setTarget(this.bungeeContractAddress as string); | ||
transaction.setPayload( | ||
txTx.data.transaction.input ? txTx.data.transaction.input : "", | ||
); //FIXME: payload = transaction input ? | ||
transactions.push(transaction); | ||
values.push(JSON.stringify(this.splitDataIntoChunks(log.data))); //FIXME: dont split, save as it is | ||
|
||
blocks.set(transaction.getId(), txBlock.data.block); | ||
} | ||
|
||
return { transactions: transactions, values: values, blocks: blocks }; | ||
} | ||
|
||
// for debug only | ||
splitDataIntoChunks(data: string) { | ||
const size = (data.length - 2) / 3; | ||
//this.logger.debug("size = " + size); | ||
const chunks = []; | ||
|
||
chunks.push("0x" + data.substring(26, 2 + size)); | ||
chunks.push(data.substring(2 + size, 2 + size * 2)); | ||
chunks.push(data.substring(2 + size * 2, data.length)); | ||
return { | ||
creator: chunks[0], | ||
isLock: parseInt(chunks[1], 16) !== 0, | ||
size: parseInt(chunks[2], 16), | ||
}; | ||
} | ||
} |
Oops, something went wrong.