github.com/muhammedhassanm/blockchain@v0.0.0-20200120143007-697261defd4d/sawtooth-core-master/sdk/examples/xo_javascript/xo_state.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 18 'use strict' 19 20 const crypto = require('crypto') 21 22 class XoState { 23 constructor (context) { 24 this.context = context 25 this.addressCache = new Map([]) 26 this.timeout = 500 // Timeout in milliseconds 27 } 28 29 getGame (name) { 30 return this._loadGames(name).then((games) => games.get(name)) 31 } 32 33 setGame (name, game) { 34 let address = _makeXoAddress(name) 35 36 return this._loadGames(name).then((games) => { 37 games.set(name, game) 38 return games 39 }).then((games) => { 40 let data = _serialize(games) 41 42 this.addressCache.set(address, data) 43 let entries = { 44 [address]: data 45 } 46 return this.context.setState(entries, this.timeout) 47 }) 48 } 49 50 deleteGame (name) { 51 let address = _makeXoAddress(name) 52 return this._loadGames(name).then((games) => { 53 games.delete(name) 54 55 if (games.size === 0) { 56 this.addressCache.set(address, null) 57 return this.context.deleteState([address], this.timeout) 58 } else { 59 let data = _serialize(games) 60 this.addressCache.set(address, data) 61 let entries = { 62 [address]: data 63 } 64 return this.context.setState(entries, this.timeout) 65 } 66 }) 67 } 68 69 _loadGames (name) { 70 let address = _makeXoAddress(name) 71 if (this.addressCache.has(address)) { 72 if (this.addressCache.get(address) === null) { 73 return Promise.resolve(new Map([])) 74 } else { 75 return Promise.resolve(_deserialize(this.addressCache.get(address))) 76 } 77 } else { 78 return this.context.getState([address], this.timeout) 79 .then((addressValues) => { 80 if (!addressValues[address].toString()) { 81 this.addressCache.set(address, null) 82 return new Map([]) 83 } else { 84 let data = addressValues[address].toString() 85 this.addressCache.set(address, data) 86 return _deserialize(data) 87 } 88 }) 89 } 90 } 91 } 92 93 const _hash = (x) => 94 crypto.createHash('sha512').update(x).digest('hex').toLowerCase().substring(0, 64) 95 96 const XO_FAMILY = 'xo' 97 98 const XO_NAMESPACE = _hash(XO_FAMILY).substring(0, 6) 99 100 const _makeXoAddress = (x) => XO_NAMESPACE + _hash(x) 101 102 module.exports = { 103 XO_NAMESPACE, 104 XO_FAMILY, 105 XoState 106 } 107 108 const _deserialize = (data) => { 109 let gamesIterable = data.split('|').map(x => x.split(',')) 110 .map(x => [x[0], {name: x[0], board: x[1], state: x[2], player1: x[3], player2: x[4]}]) 111 return new Map(gamesIterable) 112 } 113 114 const _serialize = (games) => { 115 let gameStrs = [] 116 for (let nameGame of games) { 117 let name = nameGame[0] 118 let game = nameGame[1] 119 gameStrs.push([name, game.board, game.state, game.player1, game.player2].join(',')) 120 } 121 122 gameStrs.sort() 123 124 return Buffer.from(gameStrs.join('|')) 125 }