javaeventshyperledger-sawtooth

How to create channel events using Sawtooth Java SDK?


HyperLeger Sawtooth supports subscription to events in the Transaction Processor. However is there a way to create application-specific events in the Transaction Processor something like in Python example here: https://www.jacklllll.xyz/blog/2019/04/08/sawtooth/

ctx.addEvent(
 'agreement/create',
 [['name', 'agreement'],
 ['address', address], 
 ['buyer name', agreement.BuyerName], 
 ['seller name', agreement.SellerName], 
 ['house id', agreement.HouseID], 
 ['creator', signer]],
  null)

In the current Sawtooth-Java SDK v0.1.2 the only override is

apply(TpProcessRequest, State)

Without the context. However on the documentation here: https://github.com/hyperledger/sawtooth-sdk-java/blob/master/sawtooth-sdk-transaction-processor/src/main/java/sawtooth/sdk/processor/TransactionHandler.java

addEvent(TpProcessRequest, Context)

So far I have managed to listen to events sawtooth/state-delta however this gives me all state changes of that tx-family

import sawtooth.sdk.protobuf.EventSubscription;
import sawtooth.sdk.protobuf.EventFilter;
import sawtooth.sdk.protobuf.ClientEventsSubscribeRequest;
import sawtooth.sdk.protobuf.ClientEventsSubscribeResponse;
import sawtooth.sdk.protobuf.ClientEventsUnsubscribeRequest;
import sawtooth.sdk.protobuf.Message;

EventFilter filter = EventFilter.newBuilder()
                     .setKey("address")
                     .setMatchString(nameSpace.concat(".*"))
                     .setFilterType(EventFilter.FilterType.REGEX_ANY)
                     .build();

EventSubscription subscription = EventSubscription.newBuilder()
                      .setEventType("sawtooth/state-delta")
                      .addFilters(filter)
                      .build();

context = new ZContext();
socket = context.createSocket(ZMQ.DEALER);
socket.connect("tcp://sawtooth-rest:4004");

ClientEventsSubscribeRequest request = ClientEventsSubscribeRequest.newBuilder()
               .addSubscriptions(subscription)
               .build();

message = Message.newBuilder()
          .setCorrelationId("123")
           .setMessageType(Message.MessageType.CLIENT_EVENTS_SUBSCRIBE_REQUEST)
          .setContent(request.toByteString())
          .build();

socket.send(message.toByteArray());

Once the Message.MessageType.CLIENT_EVENTS_SUBSCRIBE_REQUEST is registered I get messages in a thread loop.

I was hoping that in the TransactionHandler I should be able to addEvent() or create some type of event(s) that can then be subscribed using the Java SDK.

Has anyone else tried creating custom events in JAVA on Sawtooth?


Solution

  • Here's an example of an event being added in Python. Java would be similar. You add your custom-named event in your Transaction Processor:

    context.add_event(event_type="cookiejar/bake", attributes=[("cookies-baked", amount)])

    See https://github.com/danintel/sawtooth-cookiejar/blob/master/pyprocessor/cookiejar_tp.py#L138

    Here are examples of event handlers written in Python and Go: https://github.com/danintel/sawtooth-cookiejar/tree/master/events Java would also be similar. Basically the logic in the event handler is:

    1. Subscribe to the events you want to listen to
    2. Send the request to the Validator
    3. Read and parse the subscription response
    4. In a loop, listen to subscribed events in a loop
    5. After exiting the loop (if ever), unsubscribe rom events