The hardware and bandwidth for this mirror is donated by dogado GmbH, the Webhosting and Full Service-Cloud Provider. Check out our Wordpress Tutorial.
If you wish to report a bug, or if you are interested in having us mirror your free-software or open-source project, please feel free to contact us at mirror[@]dogado.de.
In MultiChain, Smart Filters provide a way to enforce business rules directly on the ledger. For example, you can ensure that a sensor only records values within a specific range or that a transaction is only valid if it contains certain metadata. To keep code clean, common logic can be stored in Libraries.
We start by setting up a local node. Governance permissions (Admin) are required to create filters and libraries.
A library contains helper functions. Here, we create a library called
validator that checks if a temperature reading is within a
safe physical range.
# Define the JavaScript code for the library
lib_js <- "
function isSafeTemp(temp) {
return temp >= -50 && temp <= 100;
}
"
# Create the library on the blockchain
# updatemode = 'instant' means updates take effect immediately without voting
mc_create_library(conn, "validator", updatemode = "instant", js_code = lib_js)
cat("Library 'validator' created on-chain.\n")Now we want to create a filter for a stream called
telemetry. This filter will use our library to reject any
data that has an “impossible” temperature.
The filter logic must be contained in a function named
filterstreamitem().
# The filter code imports the 'validator' library
filter_js <- "
function filterstreamitem() {
var item = getfilterstreamitem();
if (item.data.json && typeof item.data.json.temp !== 'undefined') {
if (!isSafeTemp(item.data.json.temp)) {
return 'Invalid temperature detected by on-chain logic';
}
}
return true;
}
"Before deploying a filter to the whole network, it is best practice
to test it locally using mc_test_stream_filter. To do this,
we first publish a sample item to get a valid transaction ID.
# 0. Setup a temporary stream for testing
mc_create_stream(conn, "test_stream", open = TRUE)
mc_subscribe(conn, "test_stream")
# 1. Publish valid data and get its TXID
txid_valid <- mc_publish(conn, "test_stream", "key1", list(json = list(temp = 25.5)))
# Test the filter against the valid transaction
test_valid <- mc_test_stream_filter(conn,
options = list(libraries = list("validator")),
js_code = filter_js,
tx = txid_valid)
print(test_valid) # Should be TRUE (logical) or 'true' (string)
# 2. Publish invalid data and get its TXID
txid_invalid <- mc_publish(conn, "test_stream", "key1", list(json = list(temp = 500)))
# Test the filter against the invalid transaction
test_invalid <- mc_test_stream_filter(conn,
options = list(libraries = list("validator")),
js_code = filter_js,
tx = txid_invalid)
print(test_invalid) # Should return our error message stringOnce tested, we create the filter on the blockchain and attach it to our stream.
# 1. Create the telemetry stream
mc_create_stream(conn, "telemetry", open = TRUE)
# 2. Create the stream filter globally
# Here 'options' only specifies the libraries used.
mc_create_stream_filter(conn, "temp_range_check",
options = list(libraries = list("validator")),
js_code = filter_js)
# 3. Activate the filter for the 'telemetry' stream
# In MultiChain, filters must be approved for specific entities.
admin_addr <- mc_get_addresses(conn)[1]
mc_approve_from(conn,
from_address = admin_addr,
entity = "temp_range_check",
approve = list("for" = "telemetry", approve = TRUE))After the filter is active, any attempt to publish invalid data to
the telemetry stream will be rejected by every node in the
network.
# This will SUCCEED (20 is within range)
txid_ok <- mc_publish(conn, "telemetry", "sensor_01", list(json = list(temp = 20)))
print(paste("Successful publish TXID:", txid_ok))
# This will FAIL at the protocol level.
# We use try() to catch the RPC error so the vignette can continue.
publish_error <- try(mc_publish(conn, "telemetry", "sensor_01", list(json = list(temp = 999))),
silent = TRUE)
if (inherits(publish_error, "try-error")) {
cat("Rejected! As expected, the filter blocked the invalid data.\n")
}
# Retrieve the filter code from the blockchain to verify
code_info <- mc_get_filter_code(conn, "temp_range_check")
cat("Stored filter code length:", nchar(code_info), "characters.\n")Always shut down the node and clean up the temporary directory.
# Stop the node
mc_node_stop(conn)
Sys.sleep(2)
# Determine data directory
if (.Platform$OS.type == "windows") {
base_dir <- file.path(Sys.getenv("APPDATA"), "MultiChain")
} else if (Sys.info()["sysname"] == "Darwin") {
base_dir <- file.path(Sys.getenv("HOME"), "Library/Application Support/MultiChain")
} else {
base_dir <- file.path(Sys.getenv("HOME"), ".multichain")
}
chain_dir <- file.path(base_dir, chain_name)
if (dir.exists(chain_dir)) {
unlink(chain_dir, recursive = TRUE)
}In this vignette, we demonstrated the advanced logic capabilities of
multichainr:
mc_create_library to
store JavaScript functions.mc_test_stream_filter to debug JavaScript logic without
making on-chain transactions.mc_create_stream_filter.These binaries (installable software) and packages are in development.
They may not be fully stable and should be used with caution. We make no claims about them.
Health stats visible at Monitor.