ricmoo / pycoind

Pure-Python full node and libraries for bitcoind-based crypto-currencies (eg. bitcoin, litecoin, etc)
MIT License
121 stars 45 forks source link

Messaging between pycoind nodes only #11

Open venzen opened 9 years ago

venzen commented 9 years ago

Firstly, great to see the Bitcoin protocol and blockchain functionality implemented in Python!

In the file basenode.py near line 338 you have a statement:

peer.send_message(message.Address(addresses))

I'm running two instances of pycoind-node with a non-realworld coin definition - my objective is to have a minimal blockchain implementation running as a means of experimenting - in Python as opposed to C++ (code, recompile, run, debug, etc).

However, in my use case, the interpreter complains that message is undefined in this function. I assume that connection to an existing network node will receive a message and pass it to the command_get_address() function via **kwargs. However, before I code messaging in pycoind, I wonder if you have any comments about this function. Advice as to where in pycoind to implement a Message class and constructor may help.

ricmoo commented 9 years ago

That looks like a typo on my behalf... It should read:

peer.send_message(message.Address(addresses))

I will fix it shortly.

To crete your own message, you simply define its structure. See https://github.com/ricmoo/pycoind/blob/master/pycoind/protocol/messages.py ... For example, to create a new message command singanddance, you just need to define:

class SingAndDance(Message):
    command = 'singanddance'

    properties = [
        ('song', format.FormatTypeVarString(32)),
        ('volume', format.FormatTypeNumber('I')),
    ]

The class will automatically register itself (this functionality will probably change in the future) and the node will just magically receive command_singanddance(song, volume) calls when the remote peer sends them.

Keep in mind that piecing doesn't currently validate UTXOs... The code is in-place, but turned off since it takes months to verify the blockchain... This is on of the reasons I have started this same project in node.js (which isn't quite released yet... But it's close.)

ricmoo commented 9 years ago

It should be fixed now. Let me know if you still have any more problems. Some of those code paths have not been tested.. :(

venzen commented 9 years ago

Thanks @ricmoo , it's fixed and the explanation of the magic message registration helped a lot.

Here's another one from node.py:

peer.send_message(protocol.Block(block.block_message()))

I'm getting an attr error whenever execution reaches this statement:

AttributeError: 'Block' object has no attribute 'block_message'

venzen commented 9 years ago

I changed the above send_message() call to:

peer.send_message(protocol.Block.from_block(block))

but now an error is thrown by messages.py:

I could work around that for the genesis block (block.height == 0) but its throwing the error for other blocks being requested. Perhaps the send_message() call I changed is still wrong? Any ideas?

PS - this happens between pycoind nodes. No errors are thrown when a pycoind node connects to and syncs with a Satoshi C++ node. I erased the data directory and resynced several times to eliminate possible corruption: a single pycoind node can sync with a satoshi client, no problem, but errors appear when then connecting a second pycoind node to the other.

venzen commented 9 years ago

OK, blocks are syncing between pycoind nodes.

The node.py send_message() can be made as follows:

peer.send_message(protocol.Block(block.version, block.previous_hash, block.merkle_root, 
                                          block.timestamp, block.bits, block.nonce,
                                          [t.txn for t in block.transactions]))

the code currently has block.prev_block and block.previous_block_hash in a few places, instead of block.previous_hash and I substituted with latter because it is also used in scripts/pycoind-blockchain.py.

I'll make a Pull request once I've gotten rid of a few dozen print statements :)

venzen commented 9 years ago

Regarding the automagical registration of messaging calls, I think this is a great feature, and you say:

The class will automatically register itself (this functionality will probably change in the future)

I would like to understand how this technique works and why you want to change it? In order to use and extend this feature of pycoind, can you please point me to the relevant code that enacts the automagical registration.

Also, as an example blockchain, pycoind does well, IMO. I would like to enable the UTXO validation - please point me to where it is switched off - I can code a command line argument to enable/disable this feature (disabled by default).

My objective is to allow pycoind to receive commands (via REST API, RPC or ZMQ) and to then both create and relay valid transactions. So, transaction validation would be required to make this work.