github.com/muhammedhassanm/blockchain@v0.0.0-20200120143007-697261defd4d/sawtooth-supply-chain-master/ledger_sync/subscriber/index.js (about) 1 /** 2 * Copyright 2018 Intel Corporation 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 * ---------------------------------------------------------------------------- 16 */ 17 'use strict' 18 19 const _ = require('lodash') 20 const { Stream } = require('sawtooth-sdk/messaging/stream') 21 const { 22 Message, 23 EventList, 24 EventSubscription, 25 EventFilter, 26 StateChangeList, 27 ClientEventsSubscribeRequest, 28 ClientEventsSubscribeResponse 29 } = require('sawtooth-sdk/protobuf') 30 31 const deltas = require('./deltas') 32 const config = require('../system/config') 33 34 const PREFIX = '3400de' 35 const NULL_BLOCK_ID = '0000000000000000' 36 const VALIDATOR_URL = config.VALIDATOR_URL 37 const stream = new Stream(VALIDATOR_URL) 38 39 // Parse Block Commit Event 40 const getBlock = events => { 41 const block = _.chain(events) 42 .find(e => e.eventType === 'sawtooth/block-commit') 43 .get('attributes') 44 .map(a => [a.key, a.value]) 45 .fromPairs() 46 .value() 47 48 return { 49 blockNum: parseInt(block.block_num), 50 blockId: block.block_id, 51 stateRootHash: block.state_root_hash 52 } 53 } 54 55 // Parse State Delta Event 56 const getChanges = events => { 57 const event = events.find(e => e.eventType === 'sawtooth/state-delta') 58 if (!event) return [] 59 60 const changeList = StateChangeList.decode(event.data) 61 return changeList.stateChanges 62 .filter(change => change.address.slice(0, 6) === PREFIX) 63 } 64 65 // Handle event message received by stream 66 const handleEvent = msg => { 67 if (msg.messageType === Message.MessageType.CLIENT_EVENTS) { 68 const events = EventList.decode(msg.content).events 69 deltas.handle(getBlock(events), getChanges(events)) 70 } else { 71 console.warn('Received message of unknown type:', msg.messageType) 72 } 73 } 74 75 // Send delta event subscription request to validator 76 const subscribe = () => { 77 const blockSub = EventSubscription.create({ 78 eventType: 'sawtooth/block-commit' 79 }) 80 const deltaSub = EventSubscription.create({ 81 eventType: 'sawtooth/state-delta', 82 filters: [EventFilter.create({ 83 key: 'address', 84 matchString: `^${PREFIX}.*`, 85 filterType: EventFilter.FilterType.REGEX_ANY 86 })] 87 }) 88 89 return stream.send( 90 Message.MessageType.CLIENT_EVENTS_SUBSCRIBE_REQUEST, 91 ClientEventsSubscribeRequest.encode({ 92 lastKnownBlockIds: [NULL_BLOCK_ID], 93 subscriptions: [blockSub, deltaSub] 94 }).finish() 95 ) 96 .then(response => ClientEventsSubscribeResponse.decode(response)) 97 .then(decoded => { 98 const status = _.findKey(ClientEventsSubscribeResponse.Status, 99 val => val === decoded.status) 100 if (status !== 'OK') { 101 throw new Error(`Validator responded with status "${status}"`) 102 } 103 }) 104 } 105 106 // Start stream and send delta event subscription request 107 const start = () => { 108 return new Promise(resolve => { 109 stream.connect(() => { 110 stream.onReceive(handleEvent) 111 subscribe().then(resolve) 112 }) 113 }) 114 } 115 116 module.exports = { 117 start 118 }