Skip to content

Commit

Permalink
feat(connector-fabric): add GetBlock operation to fabric connectors
Browse files Browse the repository at this point in the history
- Add common `querySystemChainCode` for executing qscc methods.
- Add new endpoint `GetBlockEndpointV1` and `getBlock` connector method
  for retrieving blocks by number, hash, or txId to the main fabric connector.
- Add similar `getBlock` function to fabric-socketio connector.
- Add functional tests to check new functions in both conenctors.

Closes: #2124

Signed-off-by: Michal Bajer <michal.bajer@fujitsu.com>
  • Loading branch information
outSH authored and petermetz committed Jul 24, 2022
1 parent ea65f6a commit 00572ed
Show file tree
Hide file tree
Showing 10 changed files with 1,340 additions and 101 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,11 @@ import { ValidatorAuthentication } from "./ValidatorAuthentication";
// Read the library, SDK, etc. according to EC specifications as needed

import { getClientAndChannel, getSubmitterAndEnroll } from "./fabricaccess";
import Client, { ProposalRequest } from "fabric-client";
import Client, { ProposalRequest, Block } from "fabric-client";
import safeStringify from "fast-safe-stringify";

const path = require("path");
const { FileSystemWallet, Gateway } = require("fabric-network");
const fs = require("fs");
const connUserName = config.read<string>("fabric.connUserName");

// Cryptographic for fabric
Expand Down Expand Up @@ -304,6 +303,105 @@ export class ServerPlugin {
});
});
}

/**
* Get fabric block specified in args.
*
* @param args
* ``` javascript
* {
* "args": {
* "contract": {"channelName": string}, // Fabric channel to execute the request on
* "args": {
* // OneOf following fields is required. First one found will be used.
* "blockNumber"?: number,
* "blockHash"?: Array<byte>,
* "txId"?: string,
* // Optional. If true, this function returns an encoded block.
* "skipDecode"?: boolean,
* }
* },
* "reqID": string // optional requestID from verifier
* }
* ```
*/
async getBlock(args: any) {
logger.info("getBlock start");

const channelName = args.contract.channelName;
const blockNumber = args.args.blockNumber;
const blockHash = args.args.blockHash;
const txId = args.args.txId;
const skipDecode = args.args.skipDecode ?? false;

const reqID = args.reqID ?? null;
logger.info(`##getBlock: reqID: ${reqID}`);

let { client, channel } = await getClientAndChannel(channelName);
await getSubmitterAndEnroll(client);

let block: Block;
if (typeof blockNumber === "number") {
block = await channel.queryBlock(
blockNumber,
undefined,
undefined,
skipDecode,
);
} else if (blockHash) {
block = await channel.queryBlockByHash(
blockHash,
undefined,
undefined,
skipDecode,
);
} else if (txId) {
block = await channel.queryBlockByTxID(
txId,
undefined,
undefined,
skipDecode,
);
} else {
const errObj = {
resObj: {
status: 400,
errorDetail:
"getBlock: Provide either blockNumber, blockHash, or txId",
},
id: reqID,
};
logger.error(errObj);
throw errObj;
}

if (!block) {
const errObj = {
resObj: {
status: 504,
errorDetail: "getBlock: Could not retrieve block",
},
id: reqID,
};
logger.error(errObj);
throw errObj;
}

const signedBlock = ValidatorAuthentication.sign({
result: block,
});

const retObj = {
resObj: {
status: 200,
data: signedBlock,
},
id: reqID,
};
logger.debug("##getBlock: response:", retObj);

return retObj;
}
} /* class */

/*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -387,6 +387,47 @@ describe("Fabric-SocketIO connector tests", () => {
expect(readSingleAsset).toEqual(firstAsset);
});

/**
* Get block by number.
*/
test("Get block by it's number works (both decoded and encoded)", async () => {
const contract = { channelName: ledgerChannelName };
const method = { type: "function", command: "getBlock" };
const argsParam = {
blockNumber: 0,
};

// Get decoded block
const response = await apiClient.sendSyncRequest(
contract,
method,
argsParam,
);
expect(response).toBeTruthy();
expect(response.status).toEqual(200);
expect(response.data).toBeTruthy();
expect(response.data.header).toBeTruthy();
expect(response.data.data).toBeTruthy();
expect(response.data.metadata).toBeTruthy();

// Get encoded block
const argsParamEncoded = {
...argsParam,
skipDecode: true,
};

const responseEncoded = await apiClient.sendSyncRequest(
contract,
method,
argsParamEncoded,
);
expect(responseEncoded).toBeTruthy();
expect(responseEncoded.status).toEqual(200);
expect(responseEncoded.data).toBeTruthy();
expect(responseEncoded.data.type).toEqual("Buffer");
expect(responseEncoded.data.data).toBeTruthy();
});

/**
* Send transaction proposal to be signed with keys attached to the request (managed by BLP),
* and then send signed transaction to the ledger.
Expand Down
5 changes: 4 additions & 1 deletion packages/cactus-plugin-ledger-connector-fabric/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,8 @@
"ngo": "2.7.0",
"node-ssh": "12.0.0",
"node-vault": "0.9.22",
"fast-safe-stringify": "2.1.1",
"sanitize-html": "2.7.0",
"openapi-types": "9.1.0",
"prom-client": "13.2.0",
"sanitize-filename": "1.6.3",
Expand All @@ -85,6 +87,7 @@
"@hyperledger/cactus-plugin-keychain-memory": "1.0.0",
"@hyperledger/cactus-test-tooling": "1.0.0",
"@types/express": "4.17.13",
"@types/sanitize-html": "2.6.2",
"@types/fs-extra": "9.0.12",
"@types/jsrsasign": "8.0.13",
"@types/multer": "1.4.7",
Expand All @@ -110,4 +113,4 @@
]
}
}
}
}

0 comments on commit 00572ed

Please sign in to comment.