From 51397fe78a3440f92dcc35393a76aa9314fac0e6 Mon Sep 17 00:00:00 2001 From: "Mark S. Lewis" Date: Wed, 3 Aug 2022 11:35:31 +0100 Subject: [PATCH] Add getCreator() to parsed transaction in off_chain_data sample (#806) Example of how the client identity that submitted a transaction can be obtained. Signed-off-by: Mark S. Lewis --- .../src/main/java/parser/ParsedPayload.java | 6 + .../main/java/parser/ParsedTransaction.java | 5 + .../app/src/main/java/parser/Transaction.java | 1 + .../application-typescript/.eslintrc.js | 99 +++++++++++++++++ .../application-typescript/.eslintrc.yaml | 103 ------------------ .../application-typescript/src/blockParser.ts | 9 ++ 6 files changed, 120 insertions(+), 103 deletions(-) create mode 100644 off_chain_data/application-typescript/.eslintrc.js delete mode 100644 off_chain_data/application-typescript/.eslintrc.yaml diff --git a/off_chain_data/application-java/app/src/main/java/parser/ParsedPayload.java b/off_chain_data/application-java/app/src/main/java/parser/ParsedPayload.java index b0463b6a..f191e94d 100644 --- a/off_chain_data/application-java/app/src/main/java/parser/ParsedPayload.java +++ b/off_chain_data/application-java/app/src/main/java/parser/ParsedPayload.java @@ -10,6 +10,7 @@ import com.google.protobuf.InvalidProtocolBufferException; import org.hyperledger.fabric.protos.common.ChannelHeader; import org.hyperledger.fabric.protos.common.HeaderType; import org.hyperledger.fabric.protos.common.Payload; +import org.hyperledger.fabric.protos.common.SignatureHeader; import org.hyperledger.fabric.protos.peer.TxValidationCode; import java.util.concurrent.atomic.AtomicReference; @@ -18,6 +19,7 @@ class ParsedPayload { private final Payload payload; private final TxValidationCode statusCode; private final AtomicReference cachedChannelHeader = new AtomicReference<>(); + private final AtomicReference cachedSignatureHeader = new AtomicReference<>(); ParsedPayload(final Payload payload, final TxValidationCode statusCode) { this.payload = payload; @@ -28,6 +30,10 @@ class ParsedPayload { return Utils.getCachedProto(cachedChannelHeader, () -> ChannelHeader.parseFrom(payload.getHeader().getChannelHeader())); } + public SignatureHeader getSignatureHeader() throws InvalidProtocolBufferException { + return Utils.getCachedProto(cachedSignatureHeader, () -> SignatureHeader.parseFrom(payload.getHeader().getSignatureHeader())); + } + public TxValidationCode getValidationCode() { return statusCode; } diff --git a/off_chain_data/application-java/app/src/main/java/parser/ParsedTransaction.java b/off_chain_data/application-java/app/src/main/java/parser/ParsedTransaction.java index ac7dc149..13c51936 100644 --- a/off_chain_data/application-java/app/src/main/java/parser/ParsedTransaction.java +++ b/off_chain_data/application-java/app/src/main/java/parser/ParsedTransaction.java @@ -29,6 +29,11 @@ final class ParsedTransaction implements Transaction { return payload.getChannelHeader(); } + @Override + public byte[] getCreator() throws InvalidProtocolBufferException { + return payload.getSignatureHeader().getCreator().toByteArray(); + } + @Override public TxValidationCode getValidationCode() { return payload.getValidationCode(); diff --git a/off_chain_data/application-java/app/src/main/java/parser/Transaction.java b/off_chain_data/application-java/app/src/main/java/parser/Transaction.java index f0188122..22513a4e 100644 --- a/off_chain_data/application-java/app/src/main/java/parser/Transaction.java +++ b/off_chain_data/application-java/app/src/main/java/parser/Transaction.java @@ -15,6 +15,7 @@ import java.util.List; public interface Transaction { ChannelHeader getChannelHeader() throws InvalidProtocolBufferException; + byte[] getCreator() throws InvalidProtocolBufferException; TxValidationCode getValidationCode(); boolean isValid(); List getNamespaceReadWriteSets() throws InvalidProtocolBufferException; diff --git a/off_chain_data/application-typescript/.eslintrc.js b/off_chain_data/application-typescript/.eslintrc.js new file mode 100644 index 00000000..351c2d0c --- /dev/null +++ b/off_chain_data/application-typescript/.eslintrc.js @@ -0,0 +1,99 @@ +module.exports = { + env: { + node: true, + es2020: true, + }, + extends: [ + 'eslint:recommended', + ], + root: true, + ignorePatterns: [ + 'dist/', + ], + rules: { + 'arrow-spacing': ['error'], + 'comma-style': ['error'], + complexity: ['error', 10], + 'eol-last': ['error'], + 'generator-star-spacing': ['error', 'after'], + 'key-spacing': [ + 'error', + { + beforeColon: false, + afterColon: true, + mode: 'minimum', + }, + ], + 'keyword-spacing': ['error'], + 'no-multiple-empty-lines': ['error'], + 'no-trailing-spaces': ['error'], + 'no-whitespace-before-property': ['error'], + 'object-curly-newline': ['error'], + 'padded-blocks': ['error', 'never'], + 'rest-spread-spacing': ['error'], + 'semi-style': ['error'], + 'space-before-blocks': ['error'], + 'space-in-parens': ['error'], + 'space-unary-ops': ['error'], + 'spaced-comment': ['error'], + 'template-curly-spacing': ['error'], + 'yield-star-spacing': ['error', 'after'], + }, + overrides: [ + { + files: [ + '**/*.ts', + ], + parser: '@typescript-eslint/parser', + parserOptions: { + sourceType: 'module', + ecmaFeatures: { + impliedStrict: true, + }, + project: './tsconfig.json', + tsconfigRootDir: process.env.TSCONFIG_ROOT_DIR || __dirname, + }, + plugins: [ + '@typescript-eslint', + ], + extends: [ + 'eslint:recommended', + 'plugin:@typescript-eslint/recommended', + 'plugin:@typescript-eslint/recommended-requiring-type-checking', + ], + rules: { + '@typescript-eslint/comma-spacing': ['error'], + '@typescript-eslint/explicit-function-return-type': [ + 'error', + { + allowExpressions: true, + }, + ], + '@typescript-eslint/func-call-spacing': ['error'], + '@typescript-eslint/member-delimiter-style': ['error'], + '@typescript-eslint/indent': [ + 'error', + 4, + { + SwitchCase: 0, + }, + ], + '@typescript-eslint/prefer-nullish-coalescing': ['error'], + '@typescript-eslint/prefer-optional-chain': ['error'], + '@typescript-eslint/prefer-reduce-type-parameter': ['error'], + '@typescript-eslint/prefer-return-this-type': ['error'], + '@typescript-eslint/quotes': ['error', 'single'], + '@typescript-eslint/type-annotation-spacing': ['error'], + '@typescript-eslint/semi': ['error'], + '@typescript-eslint/space-before-function-paren': [ + 'error', + { + anonymous: 'never', + named: 'never', + asyncArrow: 'always', + }, + ], + }, + }, + ], +}; diff --git a/off_chain_data/application-typescript/.eslintrc.yaml b/off_chain_data/application-typescript/.eslintrc.yaml deleted file mode 100644 index 13c05fb5..00000000 --- a/off_chain_data/application-typescript/.eslintrc.yaml +++ /dev/null @@ -1,103 +0,0 @@ -env: - node: true - es2020: true -extends: - - eslint:recommended -rules: - arrow-spacing: - - error - comma-style: - - error - complexity: - - error - - 10 - eol-last: - - error - generator-star-spacing: - - error - - after - key-spacing: - - error - - beforeColon: false - afterColon: true - mode: minimum - keyword-spacing: - - error - no-multiple-empty-lines: - - error - no-trailing-spaces: - - error - no-whitespace-before-property: - - error - object-curly-newline: - - error - padded-blocks: - - error - - never - rest-spread-spacing: - - error - semi-style: - - error - space-before-blocks: - - error - space-in-parens: - - error - space-unary-ops: - - error - spaced-comment: - - error - template-curly-spacing: - - error - yield-star-spacing: - - error - - after -overrides: - - files: - - "**/*.ts" - parser: "@typescript-eslint/parser" - parserOptions: - sourceType: module - ecmaFeatures: - impliedStrict: true - project: "tsconfig.json" - tsconfigRootDir: "." - plugins: - - "@typescript-eslint" - extends: - - eslint:recommended - - plugin:@typescript-eslint/recommended - - plugin:@typescript-eslint/recommended-requiring-type-checking - rules: - "@typescript-eslint/comma-spacing": - - error - "@typescript-eslint/explicit-function-return-type": - - error - - allowExpressions: true - "@typescript-eslint/func-call-spacing": - - error - "@typescript-eslint/member-delimiter-style": - - error - "@typescript-eslint/indent": - - error - - 4 - - SwitchCase: 0 - "@typescript-eslint/prefer-nullish-coalescing": - - error - "@typescript-eslint/prefer-optional-chain": - - error - "@typescript-eslint/prefer-reduce-type-parameter": - - error - "@typescript-eslint/prefer-return-this-type": - - error - "@typescript-eslint/quotes": - - error - - single - "@typescript-eslint/type-annotation-spacing": - - error - "@typescript-eslint/semi": - - error - "@typescript-eslint/space-before-function-paren": - - error - - anonymous: never - named: never - asyncArrow: always diff --git a/off_chain_data/application-typescript/src/blockParser.ts b/off_chain_data/application-typescript/src/blockParser.ts index 6ea18f27..b49acf2a 100644 --- a/off_chain_data/application-typescript/src/blockParser.ts +++ b/off_chain_data/application-typescript/src/blockParser.ts @@ -15,6 +15,7 @@ export interface Block { export interface Transaction { getChannelHeader(): common.ChannelHeader; + getCreator(): Uint8Array; getValidationCode(): number; isValid(): boolean; getNamespaceReadWriteSets(): NamespaceReadWriteSet[]; @@ -46,6 +47,7 @@ export function parseBlock(block: common.Block): Block { interface Payload { getChannelHeader(): common.ChannelHeader; getEndorserTransaction(): EndorserTransaction; + getSignatureHeader(): common.SignatureHeader; getTransactionValidationCode(): number; isEndorserTransaction(): boolean; isValid(): boolean; @@ -75,6 +77,7 @@ function parsePayload(payload: common.Payload, statusCode: number): Payload { const transaction = peer.Transaction.deserializeBinary(payload.getData_asU8()); return parseEndorserTransaction(transaction); }, + getSignatureHeader: cache(() => getSignatureHeader(payload)), getTransactionValidationCode: () => statusCode, isEndorserTransaction, isValid: () => statusCode === peer.TxValidationCode.VALID, @@ -103,6 +106,7 @@ function newTransaction(payload: Payload): Transaction { return { getChannelHeader: () => payload.getChannelHeader(), + getCreator: () => payload.getSignatureHeader().getCreator_asU8(), getNamespaceReadWriteSets: () => transaction.getReadWriteSets() .flatMap(readWriteSet => readWriteSet.getNamespaceReadWriteSets()), getValidationCode: () => payload.getTransactionValidationCode(), @@ -151,6 +155,11 @@ function getChannelHeader(payload: common.Payload): common.ChannelHeader { return common.ChannelHeader.deserializeBinary(header.getChannelHeader_asU8()); } +function getSignatureHeader(payload: common.Payload): common.SignatureHeader { + const header = assertDefined(payload.getHeader(), 'Missing payload header'); + return common.SignatureHeader.deserializeBinary(header.getSignatureHeader_asU8()); +} + function getChaincodeActionPayloads(transaction: peer.Transaction): peer.ChaincodeActionPayload[] { return transaction.getActionsList() .map(transactionAction => transactionAction.getPayload_asU8())