All Products
Search
Document Center

:Sending notary data

Last Updated:Jul 21, 2023

Data Classification

To maintain the readability of data, data classifications are set on a blockchain based on different business scenarios as the data convention for all members. Data on any blockchain must meet this convention.

Prerequisites

Before reading this Developing Demo , please contact the administrator to confirm the data classifications. If you are the administrator, please refer to Data Classification to complete the configurations. After the data classifications have been configured, users can download and unzip the SDK package, and develop sample code as illustrated in this document.

To download the SDK package, users should log on to the BaaS platform, click Blockchain List in the left-side navigation pane, and find the blockchain that you want to access. After you find the blockchain, right click more, then click Download Signed Certificate, and Download SDK.

You can check your data classifications in the file schema.txt contained in client-sdk.zip. Each classification is called a Category. You can configure multiple categories on one blockchain and each category will be assigned one unique Category ID. After the configuration is completed, users can access and filter data on the blockchain through Category ID.

Developing Demo

We will use a simple schema.txt file as an instance to show you how to construct and read notary data. You can replace the data type GuestInfo here with your own data category based on the content in your schema.txt file. In this scenario, a category named GuestInfo is declared with three members, which are username, birthday, and email. All of these members are of type String. The constraints of members are listed in the comments area.

Note

Note: please replace the data type GuestInfo here with your own data category based on the content in your schema.txt file.

// schema.txt Definition: information of guests
GuestInfo {
    String userName;  // name, not null, length within 20
    String birthday;  // birthday, not null
    String email;     // email address, not null
}

Based on the definition, we build notary data with GuestInfoBuilder in our client code.

// client code
// build notary data
GuestInfoBuilder builder = new GuestInfoBuilder();
byte[] bizData = builder.buildUserName("Bob")
                        .buildBirthday("2000-01-01")
                        .buildEmail("bob@inc.com")
                        .build();

With the notary data constructed, we next build the payload. Here the users need to use an enumeration class BizCategory. The SDK generated in this class is advance based on the data classification to help users recognize different categories. In this example, the BizCategory class would as follows.

// BizCategory class in SDK
public class BizCategory {
    public static final int GuestInfo = 0x00010001;
    ...
}

We can now pass the notary data to the payload, assign BizCategory.GuestInfo to its category, and build a notary transaction. Afterwards, we can send the transaction with the client, and the notary work is complete.

// client code
// build ContentOnlyNotary Transaction
TransactionDO tx = TransactionBuilder.getContentOnlyNotaryPayloadBuilder()
        .setContent(bizData)//set your notary data
        .setTimestamp(System.currentTimeMillis())//set time
        .setCategory(BizCategory.GuestInfo)//set category throught BizCategory
        .build();//build Transaction
// send the Transaction
Response<TransactionDO> response = client.sendTransaction(tx);

After the notary data is sent to the blockchain, we have to wait for the new block to be generated before we can query data from the blockchain. When reading data, we also use the value of BizCategory.GuestInfo to recognize the type of notary data, and cast notary data to the object. Two modules are provided to read block data. The first module is to monitor the message of new block generation and process new blocks, the second module is to pull new blocks periodically through a timed cron job. For more information refer to Best Practices .

Below are several code samples.

Sample 1. Sending notary data

// load the configuration file of client
Properties p = new Properties();
p.load(new FileInputStream("sdk.properties"));
ClientConfig config = new ClientPropertyConfig(p);

// initialize the client with the configurations
Client client = new Client(config);

// constuct the notary data
GuestInfoBuilder builder = new GuestInfoBuilder();
byte[] bizData = builder.buildUserName("Bob")
                        .buildBirthday("2000-01-01")
                        .buildEmail("bob@inc.com")
                        .build();

// build a ContentOnlyNotary Transaction
TransactionDO tx = TransactionBuilder.getContentOnlyNotaryPayloadBuilder()
        .setContent(bizData)//set notary data
        .setTimestamp(System.currentTimeMillis())//set time
        .setCategory(BizCategory.GuestInfo)//set category
        .build();//build Transaction

// send the Transaction
Response<TransactionDO> response = client.sendTransaction(tx);

if(response.isSuccess()){
  // sent successfully, save the Transaction Hash corresponding to this notary
  return tx.getTxHashValue();
}else{
  // failed sending transaction and throw an exception
  // a retry is recommended, the status of the blockchain is unknown when an RPC failed
  throw a new RuntimeException("Failed sending data to the blockchain");
}

Sample 2. Reading notary data

// get the latest block header
final Response<BlockHeader> blockHeader = client.getLatestBlockHeader();
if(!blockHeader.isSuccess()) {
    LOGGER.error("Get block header fail: ", blockHeader.getErrorMsg());
    return;
}
// oldHeight = current height of local blocks
long beginHeight = oldHeight + 1;
long finalHeight = blockHeader.getData().getHeight();
// start pulling when new blocks are found
while(beginHeight < finalHeight) {
    long endHeight = Math.min(beginHeight + FETCH_LIMIT - 1, finalHeight);
    Response<List<Block>> response = client.getBlocks((int)beginHeight, (int)endHeight);
    if (!response.isSuccess()) {
        LOGGER.error("Get response fail: ", response.getErrorMsg());
        return;
    }
    List<Block> blocks = response.getData();
    for (Block block : blocks) {
        // get notary transactions in the block
        List<TransactionDO> transactions = block.getTransactions();
        for (TransactionDO transaction : transactions) {
            // get the payload
            if (ContentOnlyNotaryPayloadDO.class.isInstance(transaction.getPayload())) {
                ContentOnlyNotaryPayloadDO contentOnlyNotaryPayloadDO =
                    ContentOnlyNotaryPayloadDO.class.cast(transaction.getPayload());
                // construct the GuestInfo object
                ByteArrayInputStream bis = new ByteArrayInputStream (contentOnlyNotaryPayloadDO.getContent());
                ObjectInputStream ois = new ObjectInputStream (bis);
                // check the category of the payload
                if (contentOnlyNotaryPayloadDO.getCategory() == BizCategory.GuestInfo) {
                    // construct the object
                    GuestInfo renter = GuestInfo.class.cast(constructUtil.construct(
                        contentOnlyNotaryPayloadDO.getContent(), GuestInfo.class));
                    // read data of renter
                    System.out.println(renter.getUserName());
                }
            }
        }
        beginHeight = block.getHeader().getHeight() + 1;
    }
}

Finally, if you want to quit, please call shutdown. The client will close the thread pool safely and quickly in shutdown().

client.shutdown();

More

Ant Blockchain uses Transaction (the model of notary transactions) to perform notarizations. The usage of ContentOnlyNotaryPayload is shown above. The business system can use other models of Transaction to communicate with the blockchain based on specific scenarios. Please refer to Notarization Transaction Models for more details.