Useful Links and Additional Reading
- How to install the Indy CLI: See Appendix A of the Indicio Selfserve Instructions
- Go to this link then click appropriate directories to see examples of Genesis files, TAA, AML, and auth_rules.
- TAA Walkthrough - instructions for adding a TAA to a network.
- Indy DID Method Specification
- RBFT Consensus Algorithm
- BFT Algorithms in Hyperledger Fabric and Indy - An excellent discussion and comparison of Consensus Algorithms in Indy and Fabric.
- Plenum read the docs
- Indy Node easy first tasks
- Hyperledger Indy Project Enhancements
Hands-On Guide
We will be extending the nym transaction in indy plenum to include an image field. We are working from the 'ubuntu-20.04-upgrade' branch.
- To get started we will create a test that writes a nym with an image, then retrieves it from the ledger, and finally checks the returned image is correct.
Inindy_node/test/nym_txn/test_nym_additional.py
around line 90 add this test.- test_nym_img
def test_nym_img(looper, sdk_pool_handle, sdk_wallet_steward, endorser_did_verkey): # prepare txn did, verkey = endorser_did_verkey nym_request, _ = looper.loop.run_until_complete( prepare_nym_request(sdk_wallet_steward, None, None, ENDORSER_STRING, did, verkey, False if verkey else True)) # modify transaction to include image hyperledger_logo = 'https://raw.githubusercontent.com/hyperledger/indy-node/master/collateral/logos/indy-logo.png' txn = json.loads(nym_request) txn['operation']['img'] = hyperledger_logo # don't do this, avoid private data on ledgers request_couple = sdk_sign_and_send_prepared_request(looper, sdk_wallet_steward, sdk_pool_handle, json.dumps(txn)) sdk_get_and_check_replies(looper, [request_couple]) # check image is in the nym rep = get_nym(looper, sdk_pool_handle, sdk_wallet_steward, did) assert rep[0][1]['result']['data'] assert json.loads(rep[0][1]['result']['data'])['img'] == hyperledger_logo
- Inside
indy_node/test/nym_txn
directory,pytest -k test_nym_img
should result in a failing test.
- Now that we have a failing test we can start updating nym write transaction types. In
indy_common/types.py
there is a class calledClientOperationField
around line 470. This class extends operations. Looks like Indy Node does not change the basic nym operations, we will borrow some code from Indy Plenum that defines a new operation. We will define in the next steps a new ClientNYMOperation. Since we are here let's add the instantiation inside _specific_operations.- nym operation
... class ClientOperationField(PClientOperationField): _specific_operations = { NYM: ClientNYMOperation(), # <----- new operation SCHEMA: ClientSchemaOperation(), ATTRIB: ClientAttribOperation(), ...
Around line 72 we will copy in the
ClientNYMOperation
class from Indy Plenum with our extraimg
field.nym operationclass ClientNYMOperation(MessageValidator): schema = ( (TXN_TYPE, ConstantField(NYM)), (ALIAS, LimitedLengthStringField(max_length=ALIAS_FIELD_LIMIT, optional=True)), (VERKEY, VerkeyField(optional=True, nullable=True)), (TARGET_NYM, DestNymField()), (ROLE, RoleField(optional=True)), (IMG, LimitedLengthStringField(max_length=RAW_FIELD_LIMIT, optional=True)) # <----- new image field )
We also need to update some imports. Some of which we will define in the next steps.
nym operation... # include ALIAS, VERKEY from plenum.common.constants from plenum.common.constants import TARGET_NYM, NONCE, RAW, ENC, HASH, NAME, \ VERSION, FORCE, ORIGIN, OPERATION_SCHEMA_IS_STRICT, OP_VER, ALIAS, VERKEY ... # include VerkeyField, DestNymField from plenum.common.messages.fields from plenum.common.messages.fields import ConstantField, IdentifierField, \ ... AnyMapField, NonEmptyStringField, DatetimeStringField, RoleField, AnyField, FieldBase, VerkeyField, DestNymField ... from plenum.config import JSON_FIELD_LIMIT, NAME_FIELD_LIMIT, DATA_FIELD_LIMIT, \ NONCE_FIELD_LIMIT, \ ENC_FIELD_LIMIT, RAW_FIELD_LIMIT, SIGNATURE_TYPE_FIELD_LIMIT, ALIAS_FIELD_LIMIT ... # include NYM, IMG from indy_common.constants from indy_common.constants import TXN_TYPE, ATTRIB, GET_ATTR, \ ... RICH_SCHEMA_PRES_DEF, RS_PRES_DEF_TYPE_VALUE, NYM, IMG
- Now that we have a test, updated operator field we need to define the '
NYM
' string constant. Insideindy_common/constants.py
define a newNYM
constant around line 14.- nym constant
# NYM IMG = "img"
- With the client operation for nym updated we will have transactions with our new "img" field. We now can update the nym handler.
inside
indy_node/server/request_handlers/domain_req_handlers/nym_handler.py
we will add a check for theimg
field, if present, store it. On line 78, add the check inside ofupdate_state
with supportingNYM
import.nym handler... from indy_common.constants import IMG, NYM <--- include NYM ... def update_state(self, txn, prev_result, request, is_committed=False): ... if IMG in txn_data: # check for IMG field new_data[IMG] = txn_data[IMG] # store IMG ...
- Inside
indy_node/test/nym_txn
directory,pytest -k test_nym_img
should result in a passing test. - Celebrate!
- You can find this coding example here, with a diff highlighting changes.