github.com/muhammedhassanm/blockchain@v0.0.0-20200120143007-697261defd4d/sawtooth-supply-chain-master/server/system/submit_utils.js (about) 1 /** 2 * Copyright 2017 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 request = require('request-promise-native') 21 const { createHash } = require('crypto') 22 const secp256k1 = require('sawtooth-sdk/signing/secp256k1') 23 const { 24 Transaction, 25 TransactionHeader, 26 TransactionList 27 } = require('sawtooth-sdk/protobuf') 28 const protos = require('../blockchain/protos') 29 30 const FAMILY_NAME = 'supply_chain' 31 const FAMILY_VERSION = '1.1' 32 const NAMESPACE = '3400de' 33 34 const SERVER = process.env.SERVER || 'http://localhost:3000' 35 const RETRY_WAIT = process.env.RETRY_WAIT || 5000 36 37 const awaitServerInfo = () => { 38 return request(`${SERVER}/info`) 39 .catch(() => { 40 console.warn( 41 `Server unavailable, retrying in ${RETRY_WAIT / 1000} seconds...`) 42 return new Promise(resolve => setTimeout(resolve, RETRY_WAIT)) 43 .then(awaitServerInfo) 44 }) 45 } 46 47 const awaitServerPubkey = () => { 48 return awaitServerInfo().then(info => JSON.parse(info).pubkey) 49 } 50 51 const encodeHeader = (signerPublicKey, batcherPublicKey, payload) => { 52 return TransactionHeader.encode({ 53 signerPublicKey, 54 batcherPublicKey, 55 familyName: FAMILY_NAME, 56 familyVersion: FAMILY_VERSION, 57 inputs: [NAMESPACE], 58 outputs: [NAMESPACE], 59 nonce: (Math.random() * 10 ** 18).toString(36), 60 payloadSha512: createHash('sha512').update(payload).digest('hex') 61 }).finish() 62 } 63 64 const getTxnCreator = (privateKeyHex = null, batcherPublicKeyHex = null) => { 65 const context = new secp256k1.Secp256k1Context() 66 const privateKey = privateKeyHex === null 67 ? context.newRandomPrivateKey() 68 : secp256k1.Secp256k1PrivateKey.fromHex(privateKeyHex) 69 70 const signerPublicKey = context.getPublicKey(privateKey).asHex() 71 const batcherPublicKey = batcherPublicKeyHex === null 72 ? signerPublicKey 73 : batcherPublicKeyHex 74 75 return payload => { 76 const header = encodeHeader(signerPublicKey, batcherPublicKey, payload) 77 const headerSignature = context.sign(header, privateKey) 78 return Transaction.create({ header, headerSignature, payload }) 79 } 80 } 81 82 const submitTxns = transactions => { 83 return request({ 84 method: 'POST', 85 url: `${SERVER}/transactions?wait`, 86 headers: { 'Content-Type': 'application/octet-stream' }, 87 encoding: null, 88 body: TransactionList.encode({ transactions }).finish() 89 }) 90 } 91 92 const encodeTimestampedPayload = message => { 93 return protos.SCPayload.encode(_.assign({ 94 timestamp: Math.floor(Date.now() / 1000) 95 }, message)).finish() 96 } 97 98 module.exports = { 99 awaitServerPubkey, 100 getTxnCreator, 101 submitTxns, 102 encodeTimestampedPayload 103 }