importhashlibimportjsonimportosimporturllib.requestfrombinasciiimportunhexlifyfromsymbolchain.BufferWriterimportBufferWriterfromsymbolchain.CryptoTypesimportHash256fromsymbolchain.symbol.Merkleimport(deserialize_patricia_tree_nodes,prove_patricia_merkle)NODE_URL=os.getenv('NODE_URL','https://reference.symboltest.net:3001')print(f'Using node {NODE_URL}')try:# Fetch the network currency mosaic IDurl=f'{NODE_URL}/network/properties'withurllib.request.urlopen(url)asresponse:props=json.loads(response.read().decode())raw_id=props['chain']['currencyMosaicId']mosaic_id=int(raw_id.replace("'",""),16)mosaic_id_hex=f'{mosaic_id:016X}'print(f'Currency mosaic ID: {mosaic_id_hex}')# Fetch the mosaic propertiesmosaic_path=f'/mosaics/{mosaic_id_hex}'print(f'Fetching mosaic from {mosaic_path}')url=f'{NODE_URL}{mosaic_path}'withurllib.request.urlopen(url)asresponse:mosaic_data=json.loads(response.read().decode())mosaic=mosaic_data['mosaic']print(json.dumps(mosaic,indent=2))# Serialize and hash the mosaic propertieswriter=BufferWriter()writer.write_int(int(mosaic['version']),2)writer.write_int(int(mosaic['id'],16),8)writer.write_int(int(mosaic['supply']),8)writer.write_int(int(mosaic['startHeight']),8)writer.write_bytes(unhexlify(mosaic['ownerAddress']))writer.write_int(int(mosaic['revision']),4)writer.write_int(int(mosaic['flags']),1)writer.write_int(int(mosaic['divisibility']),1)writer.write_int(int(mosaic['duration']),8)hashed_value=Hash256(hashlib.sha3_256(writer.buffer).digest())print(f'Hashed value: {hashed_value}')# Hash the mosaic ID to get the encoded keywriter=BufferWriter()writer.write_int(int(mosaic['id'],16),8)encoded_key=Hash256(hashlib.sha3_256(writer.buffer).digest())print(f'Encoded key: {encoded_key}')# Fetch the current network heighturl=f'{NODE_URL}/chain/info'withurllib.request.urlopen(url)asresponse:chain_info=json.loads(response.read().decode())height=int(chain_info['height'])print(f'Current height: {height}')# Fetch the block's state hash and rootsblock_path=f'/blocks/{height}'print(f'Fetching block from {block_path}')url=f'{NODE_URL}{block_path}'withurllib.request.urlopen(url)asresponse:block_data=json.loads(response.read().decode())state_hash=Hash256(block_data['block']['stateHash'])sub_cache_key='stateHashSubCacheMerkleRoots'roots=[Hash256(r)forrinblock_data['meta'][sub_cache_key]]print(f'State hash: {state_hash}')# Fetch the patricia tree pathtree_url=f'/mosaics/{mosaic_id_hex}/merkle'print(f'Fetching tree path from {tree_url}')url=f'{NODE_URL}{tree_url}'withurllib.request.urlopen(url)asresponse:tree_data=json.loads(response.read().decode())merkle_path=deserialize_patricia_tree_nodes(unhexlify(tree_data['raw']))print(f'Tree path: {len(merkle_path)} nodes')key_hex=str(encoded_key)key_pos=0fori,nodeinenumerate(merkle_path):key_pos+=node.path.sizepath_str=(f' path: {node.hex_path}'ifnode.path.sizeelse'')ifhasattr(node,'value'):print(f' [{i}] leaf{path_str} value: {node.value}')else:nibble=key_hex[key_pos]key_pos+=1active=[f'{j:X}'forj,linkinenumerate(node.links)iflink]print(f' [{i}] branch{path_str}'f' links: [{",".join(active)}]'f' -> follow {nibble}')# Verify the mosaic stateresult=prove_patricia_merkle(encoded_key,hashed_value,merkle_path,state_hash,roots)ifresult.name=='VALID_POSITIVE':print(f'Mosaic {mosaic_id_hex} state verified at height {height}')else:raiseRuntimeError(f'Mosaic {mosaic_id_hex} proof failed: {result.name}')exceptExceptionase:print(e)
importcryptofrom'crypto';import{Hash256,utils}from'symbol-sdk';import{deserializePatriciaTreeNodes,provePatriciaMerkle}from'symbol-sdk/symbol';const{hexToUint8,intToBytes}=utils;constNODE_URL=process.env.NODE_URL||'https://reference.symboltest.net:3001';console.log('Using node',NODE_URL);constsha3_256=(data)=>crypto.createHash('sha3-256').update(data).digest();constconcat=(...arrays)=>{consttotal=arrays.reduce((n,a)=>n+a.length,0);constbuf=newUint8Array(total);letoff=0;for(constaofarrays){buf.set(a,off);off+=a.length;}returnbuf;};try{// Fetch the network currency mosaic IDconstpropsRes=awaitfetch(`${NODE_URL}/network/properties`);constprops=awaitpropsRes.json();constrawId=props.chain.currencyMosaicId;constmosaicId=BigInt(rawId.replaceAll("'",''));constmosaicIdHex=mosaicId.toString(16).toUpperCase().padStart(16,'0');console.log('Currency mosaic ID:',mosaicIdHex);// Fetch the mosaic propertiesconstmosaicPath=`/mosaics/${mosaicIdHex}`;console.log('Fetching mosaic from',mosaicPath);constmosaicRes=awaitfetch(`${NODE_URL}${mosaicPath}`);constmosaicData=awaitmosaicRes.json();constmosaic=mosaicData.mosaic;console.log(JSON.stringify(mosaic,undefined,2));// Serialize and hash the mosaic propertiesconstserialized=concat(intToBytes(parseInt(mosaic.version),2),intToBytes(BigInt(`0x${mosaic.id}`),8),intToBytes(BigInt(mosaic.supply),8),intToBytes(BigInt(mosaic.startHeight),8),hexToUint8(mosaic.ownerAddress),intToBytes(parseInt(mosaic.revision),4),intToBytes(parseInt(mosaic.flags),1),intToBytes(parseInt(mosaic.divisibility),1),intToBytes(BigInt(mosaic.duration),8));consthashedValue=newHash256(sha3_256(serialized));console.log('Hashed value:',hashedValue.toString());// Hash the mosaic ID to get the encoded keyconstkeyBytes=intToBytes(BigInt(`0x${mosaic.id}`),8);constencodedKey=newHash256(sha3_256(keyBytes));console.log('Encoded key:',encodedKey.toString());// Fetch the current network heightconstchainRes=awaitfetch(`${NODE_URL}/chain/info`);constchainInfo=awaitchainRes.json();constheight=parseInt(chainInfo.height,10);console.log('Current height:',height);// Fetch the block's state hash and rootsconstblockPath=`/blocks/${height}`;console.log('Fetching block from',blockPath);constblockRes=awaitfetch(`${NODE_URL}${blockPath}`);constblockData=awaitblockRes.json();conststateHash=newHash256(blockData.block.stateHash);constroots=blockData.meta.stateHashSubCacheMerkleRoots.map(r=>newHash256(r));console.log('State hash:',stateHash.toString());// Fetch the patricia tree pathconsttreeUrl=`/mosaics/${mosaicIdHex}/merkle`;console.log('Fetching tree path from',treeUrl);consttreeRes=awaitfetch(`${NODE_URL}${treeUrl}`);consttreeData=awaittreeRes.json();constmerklePath=deserializePatriciaTreeNodes(hexToUint8(treeData.raw));console.log('Tree path:',merklePath.length,'nodes');constkeyHex=encodedKey.toString();letkeyPos=0;merklePath.forEach((node,i)=>{keyPos+=node.path.size;constpathStr=node.path.size?` path: ${node.hexPath}`:'';if('value'innode){console.log(` [${i}] leaf${pathStr} value: ${node.value}`);}else{constnibble=keyHex[keyPos];keyPos+=1;constactive=node.links.map((l,j)=>(l?j.toString(16).toUpperCase():null)).filter(x=>x!==null);console.log(` [${i}] branch${pathStr}`+` links: [${active}]`+` -> follow ${nibble}`);}});// Verify the mosaic stateconstresult=provePatriciaMerkle(encodedKey,hashedValue,merklePath,stateHash,roots);if(result===0x0001){// VALID_POSITIVEconsole.log(`Mosaic ${mosaicIdHex} state verified at height ${height}`);}else{thrownewError(`Mosaic ${mosaicIdHex} proof failed: ${result}`);}}catch(e){console.error(e.message);}
# Serialize and hash the mosaic propertieswriter=BufferWriter()writer.write_int(int(mosaic['version']),2)writer.write_int(int(mosaic['id'],16),8)writer.write_int(int(mosaic['supply']),8)writer.write_int(int(mosaic['startHeight']),8)writer.write_bytes(unhexlify(mosaic['ownerAddress']))writer.write_int(int(mosaic['revision']),4)writer.write_int(int(mosaic['flags']),1)writer.write_int(int(mosaic['divisibility']),1)writer.write_int(int(mosaic['duration']),8)hashed_value=Hash256(hashlib.sha3_256(writer.buffer).digest())print(f'Hashed value: {hashed_value}')# Hash the mosaic ID to get the encoded keywriter=BufferWriter()writer.write_int(int(mosaic['id'],16),8)encoded_key=Hash256(hashlib.sha3_256(writer.buffer).digest())print(f'Encoded key: {encoded_key}')
// Serialize and hash the mosaic propertiesconstserialized=concat(intToBytes(parseInt(mosaic.version),2),intToBytes(BigInt(`0x${mosaic.id}`),8),intToBytes(BigInt(mosaic.supply),8),intToBytes(BigInt(mosaic.startHeight),8),hexToUint8(mosaic.ownerAddress),intToBytes(parseInt(mosaic.revision),4),intToBytes(parseInt(mosaic.flags),1),intToBytes(parseInt(mosaic.divisibility),1),intToBytes(BigInt(mosaic.duration),8));consthashedValue=newHash256(sha3_256(serialized));console.log('Hashed value:',hashedValue.toString());// Hash the mosaic ID to get the encoded keyconstkeyBytes=intToBytes(BigInt(`0x${mosaic.id}`),8);constencodedKey=newHash256(sha3_256(keyBytes));console.log('Encoded key:',encodedKey.toString());
# Fetch the current network heighturl=f'{NODE_URL}/chain/info'withurllib.request.urlopen(url)asresponse:chain_info=json.loads(response.read().decode())height=int(chain_info['height'])print(f'Current height: {height}')# Fetch the block's state hash and rootsblock_path=f'/blocks/{height}'print(f'Fetching block from {block_path}')url=f'{NODE_URL}{block_path}'withurllib.request.urlopen(url)asresponse:block_data=json.loads(response.read().decode())state_hash=Hash256(block_data['block']['stateHash'])sub_cache_key='stateHashSubCacheMerkleRoots'roots=[Hash256(r)forrinblock_data['meta'][sub_cache_key]]print(f'State hash: {state_hash}')
// Fetch the current network heightconstchainRes=awaitfetch(`${NODE_URL}/chain/info`);constchainInfo=awaitchainRes.json();constheight=parseInt(chainInfo.height,10);console.log('Current height:',height);// Fetch the block's state hash and rootsconstblockPath=`/blocks/${height}`;console.log('Fetching block from',blockPath);constblockRes=awaitfetch(`${NODE_URL}${blockPath}`);constblockData=awaitblockRes.json();conststateHash=newHash256(blockData.block.stateHash);constroots=blockData.meta.stateHashSubCacheMerkleRoots.map(r=>newHash256(r));console.log('State hash:',stateHash.toString());
# Verify the mosaic stateresult=prove_patricia_merkle(encoded_key,hashed_value,merkle_path,state_hash,roots)ifresult.name=='VALID_POSITIVE':print(f'Mosaic {mosaic_id_hex} state verified at height {height}')else:raiseRuntimeError(f'Mosaic {mosaic_id_hex} proof failed: {result.name}')