Disclaimer: I work on STX and its blockchain
1,156 karma · joined November 15, 2013
Disclaimer: I work on STX and its blockchain
Disclaimer: I work on STX and its blockchain
[1] https://www.sec.gov/Archives/edgar/data/1693656/000110465919...
Yes there is. You register them as securities. STX[1] did this. Other projects need to suck it up and do it legally.
[1] disclaimer: I work on the Stacks blockchain (STX)
What's the cost of this? Why, it's the very same as the cost of getting most everyone vaccinated for literally anything else we get vaccinated for! No one has a conniption about vaccine regimens for measles, mumps, polio, etc., because the programs for implementing them at scale have been so successful that hardly anyone gets hospitalized or dies from them anymore. Want to attend public school? Get vaccinated. Want to join the military? Get vaccinated. Want to live in a college dorm? Get vaccinated.
The marginal cost of adding one more required vaccine on top of the ones almost everyone regularly gets (and almost no one complains about) in order to participate in normal society is negligeable.
So no, it's not a case of "everyone gets corona" vs "everyone gets corona and we have a miserable digital dystopia", as you put it. It's a choice of "everyone gets corona and a lot of other people needlessly die for want of medical care" vs "everyone gets corona and/or the vaccine, you have to fill one more checkbox on your vaccine card (which already has a dozen or so), and comparatively fewer people die for want of medical care." Life will get back to normal either way; at this point it's really a question of dealing with the selfish, paranoid, delusional, despicable people who would rather see the mass death of their fellow countrymen over having to fill one more checkbox on their vaccine card.
It can be done. We banned CFCs after all.
I use Chromium because it has both a safer and more reliable design and implementation. If web browsers were OS's, Firefox would be Mac OS 9. If Mozilla wants to understand why they're losing market share, they should try and understand why no one builds OS's like that anymore.
And boy does it show!
How do you debug your smart contract? Your users tell you their money got stolen out of it. I wish that was a joke.
> Also, if you're just going to replace one immutable contract with another, you're back to meatspace and re-negotiation, which can be time consuming and expensive.
Is upgrading them in place somehow better? At least by keeping the old systems around, the people who still get mileage out of them aren't sold up-river.
Hate to break it to you, but if your consensus rules permit forks, then there's no getting around this. A fork can be mined arbitrarily far in the future that builds off of a block arbitrarily far in the past.
We intend to partition state by application, for applications that are willing to trade smart contract composibility for more block space: https://gist.github.com/jcnelson/c982e52075337ba75e00b799421...
> But then again if you're building it on top of the literal money fire that is bitcoin, who cares about scalability and resource use!
Show me a more resilient blockchain and we'll build on that instead. Popular systems see lots of usage; news at 11.
My point is that a piece of software does not need an upgrade procedure if there exists a way to install a newer copy without touching the old one. Trying to build an upgrade procedure when there is always the option to install a newer version this way (especially if it can seamlessly access the older version's state) is at best over-engineering.
> Out of curiosity, how does this typically get exposed in dApps (or wallet UIs) built on Stacks?
This is being done right now with Stacks' on-chain naming system, which is realized as a smart contract. The new naming system does not need to import any state from the old system in order to resolve pre-existing names, nor does the existing naming system need to be disabled, because the new system is instead able to call the name resolution method via this "run read-only code on the chainstate as of this block" feature. The past is immutable, so future changes to the state of the old system beyond a predetermined sunset block (defined in the new contract) will not be visible to the users of the new system.
Consider this example. Suppose the name "alice.btc" was registered at block 1000 (hash 0x123) in the old system, and suppose the new system was deployed to use all the state in the old system up to block 1001 (hash 0xabc). Resolving alice.btc in the new system runs code to the effect of:
(let (
(alice-rec (at-block 0xabc
(contract-call? 'SP000000000000000000002Q6VF78.bns name-lookup? "alice.btc")))
)
;; Do something with alice-rec
)
Internally, the (at-block) function runs the given code body with access to the system state as it was as of the end of block 0xabc. The system state is represented internally as a set of key/value pairs indexed by a forest of authenticated hash tries which make it efficient to query a key as of a particular block (see https://github.com/stacksgov/sips/blob/main/sips/sip-004/sip... for details).Suppose bob.btc was registered in block 1002 (hash 0xdef). The above (at-block) call will not resolve bob.btc in the old contract, because its state was written after the sunset block 0xabc.
So why build an upgrade procedure at all, when you don't have to?
> On the Ethereum blockchain (for instance) storage and smart contracts are tightly coupled.
Sounds like an unforced error on these smart contracts' authors parts, and should not be used as an excuse to compromise the principle of code immutability.
If the possibility existed that they need to replace the business logic at a later date, then they should factor the storage logic so as to avoid this coupling. It can be done -- for example, a smart contract dapp can leverage a shared contract that only implements a public key/value store, where the keys are prefixed by the calling contract's address. Then, when the business logic contract changes, it can access any old versions' state with the old versions' contract address, apply any migrations on-the-fly, and store new state that will not overwrite old state due to this key prefixing.
In the Stacks blockchain (which I work on), we go one step further by making it so you can run an arbitrary read-only code snippet on the state of the blockchain at any point in the past (as given by a block hash). Then, you don't even need to do any migrations -- you can just query the historic state of your old contract and only store new data once it's necessary.
First, if you're saying that you need a way to upgrade your money-managing code periodically because you will likely ship versions of it with show-stopping bugs (such as those that enable the destruction or theft of the users' funds), then why should I trust that you will ship flawless code for upgrades?
Second, if the combined security budget of the people who can carry out the upgrade is less than that of the majority of the block producers on the chain, then why build an upgrade procedure at all? Why risk it? Instead, just deploy a new version of the smart contract, and ask users to use that one instead. If it gets confirmed, then an honest majority of block producers will ensure that it stays confirmed. This takes no code at all. You simply sign the new code with the same key that deployed the old code to demonstrate that it originates from the same author(s). Let users decide on their own whether or not to use your upgraded code -- after all, it might introduce new bugs, and the "bugs" you are fixing might be features to other people. It's not your place to tell users what version of the code should be used, and what should not be used.
I stopped reading here. First, this is factually wrong -- the software industry has tons of experience dealing with software that can't be upgraded. Ever try to upgrade the firmware on a chip with no I/O facility for doing so? The answer is you don't; you instead focus on getting the code correct the first time, and possibly you build out a way to recall the product and replace it with a fixed version and price in the risk of needing to do so into the product itself. It can be done; it just takes discipline.
Second, if you don't understand why smart contracts being immutable is a necessary and desirable feature of the system, not a bug, then you're not going to understand much of web3. Like, think about it for five minutes -- if your smart contracts can be upgraded by default, and this code manages valuable digital assets, then their code can be replaced with code that steals those assets. Making this very, very, very hard is deliberate.
/// A state machine that adds three numbers and uploads them to a web server
struct AddAndUpload {
/// I/O handle to the event loop
io: IOClient,
/// Buffer to store numbers I load
nums: [u64; 3],
/// URL to upload the data to
url: String
}
impl AddAndUpload {
/// Constructor
pub fn new(io: IOClient, url: String) -> AddAndUpload {
AddAndUpload {
io,
nums: [0u64; 3],
url
}
}
/// Entry point to this state machine
pub fn inner_main(&mut self) -> Result<(), IOClient::Error> {
/// go and get the data
let n1_fut : IOClient::Future<u64> = self.io.sql_async("SELECT n1 FROM table1", &[])?;
let n2_fut : IOClient::Future<u64> = self.io.sql_async("SELECT n2 FROM table2", &[])?;
let n3_fut : IOClient::Future<u64> = self.io.sql_async("SELECT n3 FROM table3", &[])?;
// wait for all I/O operations to finish
IOClient::wait_all(&[&n1_fut, &n2_fut, &n3_fut])?;
// extract results
let n1 = n1_fut.into_inner();
let n2 = n2_fut.into_inner();
let n3 = n3_fut.into_inner();
// upload them
let sum = n1 + n2 + n3;
let upload_fut : IOClient::Future<IOClient::HTTPStatus> = self.io.http_post_async(&self.url, &["content-type: application/octet-stream"], &sum.to_be_bytes())?;
let upload_http_status = upload_fut.wait()?.into_inner();
match upload_http_status.as_u16() {
200 => {
Ok(())
}
400..499 => {
Err(IOClient::Error::Custom("client error"))
}
500..599 => {
Err(IOClient::Error::Custom("server error"))
}
x => {
Err(IOClient::Error::Custom("Nonsensical HTTP code"))
}
}
}
}
impl IOClient::StateMachine for AddAndUpload {
type Return = ();
fn main(&mut self) -> Result<(), IOClient::Error> {
self.inner_main()
}
}
/\* somewhere else \*/
fn main() {
let io_server = IOServer::spawn().unwrap();
let io_client = io_server.client().unwrap();
let add_and_upload = AddAndUpload::new(io_client, "http://example.com".to_string());
loop {
io_server.run().unwrap();
match add_and_upload.get_machine_status() {
Ok(IOClient::StateMachine::Finished(result)) => {
eprintln!("add_and_uploaded exited with {:?}", &result);
break;
}
Ok(_) => {},
Err(e) => {
panic!("add_and_upload aborted: {:?}", &e);
}
}
}
io_server.terminate();
}I think this is the most underappreciated part of this article. Since when did everything have to be async? There are other ways to represent concurrency that more accurately reflect what the computer is actually doing.
For example, an alternative to async is to represent a workstream as a state machine, where state transitions happen between I/O. Then, your state machine can be a struct, and each state transition can be an impl function on that struct that takes one or more completed I/O requests as input and emits one or more I/O requests as output. This saves you from having to implement everything as a closure, which this article rants about. Your top-level epoll loop merely services I/O requests from state machine instances, and invokes your global application logic to start and stop state machines to carry out business logic tasks.
I realize that many complicated workstreams could have many states due to all the I/O they might do, but the task of converting a high-level workstream into a state machine could be automated by the tooling.
This is what makes religious indoctrination that much harder to shake off. If you truly believe that you will face divine and eternal punishment for becoming apostate, or will receive divine and eternal rewards for adhering to the faith, then you'd naturally take the latter path even if only out of your own self-interest. Breaking out of this mental model requires recognizing the psychological manipulation for what it is, despite having known no other mental framework.
By contrast, racism and Nazism do not manipulate you this way. They instead appeal to your senses of grievance, entitlement, and resentment, in a way that enhances your self-esteem. While this can also be difficult to break away from, the psychological barriers for doing so are a lot lower -- like, you're not dealing with eternal consequences.
But regardless, the topic at hand is whether or not religious or political discrimination are acceptable when it comes to using a platform like Twitter. I'd say "yes" in both cases -- Twitter isn't a vital service (compared to, say, housing, banking, or employment), and you not having a Twitter account does not inhibit your ability to hold and act on either your religious or political beliefs.