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 <mark_lewis@uk.ibm.com>
This commit is contained in:
Mark S. Lewis 2022-08-03 11:35:31 +01:00 committed by GitHub
parent cb4355125f
commit 51397fe78a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 120 additions and 103 deletions

View file

@ -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<ChannelHeader> cachedChannelHeader = new AtomicReference<>();
private final AtomicReference<SignatureHeader> 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;
}

View file

@ -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();

View file

@ -15,6 +15,7 @@ import java.util.List;
public interface Transaction {
ChannelHeader getChannelHeader() throws InvalidProtocolBufferException;
byte[] getCreator() throws InvalidProtocolBufferException;
TxValidationCode getValidationCode();
boolean isValid();
List<NamespaceReadWriteSet> getNamespaceReadWriteSets() throws InvalidProtocolBufferException;

View file

@ -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',
},
],
},
},
],
};

View file

@ -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

View file

@ -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())