') + ')', 'gi'); if (regex.test(text)) { found = true; var frag = document.createDocumentFragment(); var parts = text.split(regex); parts.forEach(function(part, i) { if (i % 2 === 0) { frag.appendChild(document.createTextNode(part)); } else { var span = document.createElement('span'); span.className = 'userscript-highlight'; span.textContent = part; frag.appendChild(span); } }); node.parentNode.replaceChild(frag, node); } }); } else if (node.nodeType === 1 && node.childNodes) { // element var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT']; if (!skipTags.includes(node.tagName)) { Array.from(node.childNodes).forEach(highlight); } } } highlight(document.body); // Re-highlight on dynamic content var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1 || node.nodeType === 3) highlight(node); }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ', 'i'); if (__m === '*' || __re.test(location.href)) { // Strip utm_, fbclid, gclid, etc. from all links on page (function() { var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content', 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid', 'ref', 'ref_src', 'source', 'medium', 'campaign']; function cleanUrl(url) { try { var u = new URL(url, window.location.origin); var changed = false; trackingParams.forEach(function(p) { if (u.searchParams.has(p)) { u.searchParams.delete(p); changed = true; } }); return changed ? u.toString() : url; } catch (e) { return url; } } function cleanLinks() { document.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } cleanLinks(); var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1) { if (node.tagName === 'A') cleanLinks(); node.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + ', 'i'); if (__m === '*' || __re.test(location.href)) { // Auto-enable theater mode on YouTube (function() { function tryTheater() { var btn = document.querySelector('button[aria-label="Theater mode"], ytd-player #player button[title="Theater mode"]'); if (btn && !btn.classList.contains('activated')) { btn.click(); } } // Try immediately tryTheater(); // Try after navigation (SPA) var lastUrl = location.href; setInterval(function() { if (location.href !== lastUrl) { lastUrl = location.href; setTimeout(tryTheater, 500); } }, 1000); // Also try on player load var observer = new MutationObserver(tryTheater); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ', 'i'); if (__m === '*' || __re.test(location.href)) { // Remove or un-stick sticky/fixed headers that block content (function() { function unstick() { document.querySelectorAll('header, nav, [role="banner"], .header, .navbar, .sticky, .fixed-top, [style*="position: fixed"], [style*="position:sticky"]').forEach(function(el) { if (el.style.position === 'fixed' || el.style.position === 'sticky' || getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') { el.style.position = 'static'; el.style.top = 'auto'; el.style.zIndex = 'auto'; } }); } unstick(); var observer = new MutationObserver(unstick); observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] }); })(); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); })(); GitHub - whfuyn/executor_chaincode: A chaincode-compatible executor for CITA-Cloud. · GitHub
Skip to content

Repository files navigation

executor_chaincode

Build Status

Update: I've added CouchDB and EventHub support for executor_chaincode. But unfortunately, it's not allowed to be open source, neither the code improvements are backported here. Only the docker image is openly available, here.

executor_chaincode is an implementation of CITA-Cloud's executor.

It's compatible with fabric's chaincode with some limitations.

Users can write their smart contracts in chaincode, and run it in CITA-Cloud.

Usage

1. Executor

cargo build --release

To build docker image:

docker build -t citacloud/executor_chaincode .

You may find more details in runner_k8s and runner_consul

2. Chaincode

Build your chaincode and run it after the executor started.

You need to run a chaincode instance for each executor.

Note that some environment variables need to be set.

CORE_PEER_LOCALMSPID="Org1MSP" \
CORE_PEER_TLS_ENABLED="false" \
CORE_CHAINCODE_ID_NAME="asset-transfer-secured-agreement" \
./tradingMarbles --peer.address 127.0.0.1:7052

In fabric, some transaction can only be simulated and endorsed by peers in the same org with the client.

  • CORE_PEER_LOCALMSPID represents the org of the peer running this chaincode server.

    Due to the different executing models of transactions between CITA-Cloud and fabric, constraining a transaction to be executed in a specific executor is infeasible. So the org check in the asset-transfer-secured-agreement is removed.

  • CORE_PEER_TLS_ENABLED is not supported yet.

  • CORE_CHAINCODE_ID_NAME is the name of the chaincode.

  • --peer.address is the executor's address. Chaincode will register itself to the executor to start a bidirectional request/response stream.

You may check ./examples to see some chaincodes examples from fabric-samples.

3. Send transaction

Transaction data is the concat of chaincode_name.len().to_be_bytes()chaincode_namepayload.

Transactions in a finalized block will be executed by sending its payload to the chaincode indicated by chaincode_name.

The chaincode, as a standalone server, expect a ChaincodeMessage defined in fabric-protos/peer/chaincode_shim.proto

The detail format of the ChaincodeMessage is complicated, but its basic structure is:

ChaincodeMessage{r#type:ChaincodeMsgType::Transactionasi32,// This payload contains the function name to be called and its args.
payload,
txid,
channel_id,// signed_proposal is used to provide caller's identity and this call's private data.proposal:Some(signed_proposal),
..Default::default()}

I write a library for building and sending this kind of transaction.

Limitations

1. Private data and organization check

Since transactions are executed equally on every peers, organization check that verify peer and client org match will fail, and private data attached to the transaction will be sent to and stored by every peers.

2. Channel

Channel is not supported yet. Users may run multiple CITA-Cloud instances to simulate channel.

3. Pagination

Paginated queries are not supported yet. Queries will return full results at once.

4. Invoke other chaincodes

Invoking other chaincodes is not supported yet.

5. DB specified queries

Update: supported in executor_chaincode_ext.

ctx.GetStub().GetQueryResult(queryString)

This kind of DB specified queries is not supported yet.

About

A chaincode-compatible executor for CITA-Cloud.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages