Proof-of-concept VM Development


#1

So i’ve recently started to develop a minimal pure python Virtual Machine tailored specifically for counterparty. I’m starting this thread to keep note of development and design decisions, and also to get input from the community regarding what should the VM do.

FAQ

  • Why not use EVM?
    • EVM was designed with ethereum blocktimes and specifics in mind. CP has already a lot of groundwork regarding tokens, bets and a lot of useful functions that don’t need to be recoded in a smart contract.
  • Isn’t a VM a very large and complicated endeavor?
    • A general purpose VM is a very complex piece of software. A domain specific one isn’t. The target of the CPVM is to have the least amount of instructions available to give enough functionality to contract writers to operate over CP without breaching security or leaving gaping security holes for anyone to exploit.
  • Assembler! Really?
    • It isn’t as bad as it looks, look at the examples and you’ll see that there are several high level functions in the assembly language of CPVM to allow any new contract writer to learn quickly.
  • Why pure python? wouldn’t C or C++ would be a better implementation language because of it’s speed?
    • Any piece of code that you make on C/C++ is prone to throw certain exceptions out of the python code that could kill the CP server without letting it first catch exceptions inside the python code.

More info on the next post.


Smart Contracts - Which options do we have?
#2

Current design

The VM is a memoryless, pure register based machine. It currently has the following registers:

  1. “filter”: A filter register, useful for querying CP tables. It needs to be pushed to the filter list to be useful.
  2. “filterlist”: The filter list sent for queries to the CP database.
  3. “filterop”: The filter operation used to combine the filters on the query.
  4. “table”: The table to be queried.
  5. “ob[8]”: 8 registers dedicated to object storage.
  6. “list[8]”: 8 registers dedicated to list storage.
  7. “int[16]”: 16 registers dedicated to integer storage.
  8. “z”: The working register. Stores the results of comparisons and several other ops.
  9. “line”: The current line of execution of the contract.
  10. “stack”: A stack list of the return points used for method calling.

Also, current operations for the initial coded part are:

  1. “clear”: clear a register to its initial state.
  2. “filterop”: change the current filter operation.
  3. “table”: change the current table to be queried.
  4. “filter”: change the current filter field to a given value.
  5. “push”: push a concept to its corresponding list. Currently it only supports filter as parameter.
  6. “get_table”: query the current table with the current filter list.
  7. “load_len”: load the length of a given list to a given int register.
  8. “rlcmp”: compare a register to a literal. Currently only supports comparing int registers. Sets working register to -1 if below the literal, to 1 if above or 0 if equal.
  9. “jz”: jump to label if working register is zero.
  10. “jnz”: jump to label if working register is not zero.
  11. “jmp”: unconditional jump to label.
  12. “rlsum”: sum a register with a literal and put the result to the working register.
  13. “movr”: move the working register to a given int register.
  14. “loadob”: load an object register specified by a literal from a list with an int register working as an index.
  15. “call”: jump to a label saving the current line to the stack.
  16. “return”: pop the stack and set the current line number to its value.
  17. “obcmp”: compare a field of an object to a given value. Put result on register as “cmp” would do.
  18. “throw”: throw an exception.
  19. “finish”: finish the program successfully.
  20. “print”: print debug information.

The current implementation lets the VM be stepped conditionally, so we can control gas prices and even remote control (although not implemented) execution of contracts if a control address switches it on or off (the belated killswitch).

As you can see, it is very basic and still can’t do anything useful, but it’s a start.


#3

This is a great start John! I am really enjoying watching all the amazing stuff your bringing to the CP community… CIP10, rarepepeparty, counterparty-dns, CP VM… your single-handedly setting us on a moon trajectory :slight_smile:


Betting - Equal/NotEqual vs Less/NotLess
CIP Draft - Instant Lottery
#4

Have you considered making the VM intentionally NOT Turing complete?

Sure you can’t play chess. But do we really need Turing complete smart contracts?

By making the VM language non-turing complete, it makes calculating gas usage much, much easier. And it makes security easier to reason about.


#5

That’s not a bad idea at all. In fact, the first idea that came up to me was to intentionally neuter jumps (but it’s hard to make an smart contract without jumps).

EDIT: Maybe make jumps only be able to jump forward, so there can’t exist any looping.


#6

Great stuff John!


#7

Yay! Been waiting since long ago. Smart contract on counter party :ok_woman:


#8

Don’t hold your breath though, This is just a proof of concept for now.


#9

I would note Dave Collins’ opinion on VM design is quite interesting:

However, I suspect you’re really asking if Decred will ever implement them in the way something like Ethereum has. Since Decred is driven by stakeholders, I can’t answer definitively what it will ultimately have, but I will give my personal opinion on the direction I (and others on the team) would like to see it go.

So, one of the first things that I would not want to see is for the system to be Turing complete. It is simply not necessary and is a liability. All useful smart contracts must terminate, so it follows that it is reasonable to restrict the underlying language to primitives which allow the contracts to be provably terminating. Once you have restricted the underlying language in this fashion, it can no longer be Turing complete. For example, one such paradigm is total functional programming. Notice that the restrictions which allow the program to be provably terminating disqualify it from being TC.

Next up, I would like to see a high-level language created that compiles down to the script system primitives (opcodes) in order to make it significantly easier to write smart contracts.

Another key point, in my opinion, is that it’s really not sufficient to just have a platform for running dapps or a given smart contract. Truly useful smart contracts require an entire ecosystem around them. As a result, I would prefer to see the bulk of work on smart contracts in Decred in general approached from a more holistic standpoint where the focus is put on creating specific smart contracts that are actually useful and provide value and the necessary external infrastructure – aka the entire ecosystem.

Counterparty would surely outshine Ethereum with such a VM, see: https://www.reddit.com/r/btc/comments/6j7eby/ethereum_bitcoins_competitor_ally_or_both/djcbvym/?context=3

I would also note the Counterparty reference implementation in Python receives basically zero ongoing development.

To truly launch Counterparty into the future, IMHO the very first thing that should happen is a ground up reimplementation of the entire system, e.g. a rewrite in:

I personally lean towards C++ given libbitcoin-server can sync from genesis to present in 16 minutes flat on 128 cores with address indexing. This type of addrindex performance is impossible to come across elsewhere.

Counterparty’s use in gamedev, which is disproportionately C++ based, also makes me lean towards developing a C based ecosystem.


#10

Yeah, general consensus around VMs is that turing completeness isn’t necessary.

I was considering implementing the VM in prolog, but i’m a little bit rusty there so didn’t go for it.

For now the design is just a simple opcode based assembly with certain functions neutered to remove turing completeness.

Regarding code rewrite, that would be completely out of question with current funding status (read: none, just bounties for cips).

However, if you asked me… i would go for BCoin. Their codebase is WAY cleaner than most out there, and it’s pretty extensible. IIRC they have an addrindex implementation too, so it wouldn’t be too crazy to use it instead of bitcoin core.


#11

At a bare minimum, counterparty-server’s reliance on a fork of Bitcoin Core with addrindex is problematic. Even if we were on good terms with Bitcoin Core, they’ve failed to merge addrindex functionality for years. The patch we’re relying on as a workaround is practically unmaintained.

btcd, bcoin and libbitcoin all feature native address indexing, so switching to any one of these altnodes on the backend would be a major step in the right direction for Counterparty. It would also be simple enough to not require a rewrite. To that end, would be interesting to discuss e.g. funding a Venezuelan full time dev team for Counterparty, paid in digital currency, but that is getting off-topic here.

It’d be crazy not to use bcoin/btcd/libbitcoin. We must break the dependency on our patched version of Bitcoin Core.

Something to consider about BCoin, however; BCoin includes native C code for performance reasons. Hence, BCoin is going to ship a mixed JS/C codebase forever and ever. Not that I don’t trust JJ to write C, but impurity creates complications.

Conversely, btcsuite is pure Go, and Go has very nice deployment properties. Nicer than JS and much nicer than C++. I also see @rubensayshi is contributing some code to btcsuite.

JS makes a lot of sense when writing consumer facing software that is intended to run inside a web browser. Also, the immensity of the JS ecosystem makes it a stronger contendor than Python for a wide range of uses IMO; but I’m biased there, I’m not a fan of Python whatsoever so JS being better than Python doesn’t mean much.

Enterprise server deployments are in a different category, and for what we’re doing with indexing the blockchain, and parsing the blocks for Counterparty data, I think you pretty much have to favor C++ and Go over JS.


#12

It is easy to underestimate just how big of a project this is. This isn’t going to happen unless a community of developers rallies around it and puts some serious development time into it.

+1 for bcoin. This implementation is well supported and has what we need.


#13

When Polo?