this is an experimental library used as a demo of the idea of Proof-of-Play
Codes of the paper (BSCI 2019, Workshop under ASIACCS 2019):
Proof-of-Play: A Novel Consensus Model for Blockchain-based Peer-to-Peer Gaming System,
Ho Yin Yuen (The Hong Kong Polytechnic University, China); Feijie Wu (The Hong Kong Polytechnic University, China); Wei Cai (The Chinese University of Hong Kong, Shenzhen, China); Henry C.B. Chan (The Hong Kong Polytechnic University, China); Qiao Yan (Shenzhen University, China); Victor C.M. Leung (Shenzhen University, China)
link to paper: https://doi.org/10.1145/3327960.3332386
There is dependence has to be taken care of before using the library:
- Flask
- numpy
- py2p
- pycryptodome
- rehash (url: https://github.com/kislyuk/rehash)
To avoid issues in installation, please use anaconda prompt and create a virtual env (anaconda download link: https://www.anaconda.com/distribution/)
Steps:
after install anaconda, open anaconda prompt and do the following:
conda create -n myPoP python=3.7
pip install numpy
pip install py2p
pip install flask
pip install pycryptodome
pip install rehash
the PoP object can be initialized as following:
import PoP
PoP.handler(nodeID="Alice", winnerFunc=None, ratingFunc=None, setupJSON=setupJSON)
where setupJSON is the parameter of your PoP blockchain and PoP game
setupJSON = {
"nodeID": str(nodeID), # the ID of the player, aka an account name
"game_port": 1000, # the sock port players exchange and verify their game results of the same match
"blockchain_port": 1001, # the sock port players host their blockchain entry
"API_port": 1002, # the sock port players trigger the event of game_port
"blockchain_bootstrap_ip": None, # the ip address of one of the full node blockchain, a bootstrap
# not full parameters are configurated, default paramters will be intialized if it doesn't present in setupJSON
}
the folder ran the above code will then initialized as a PoP project with a config folder, with a .json file storing above setupJSON
to activate a blockchain one must create a genesis. It defines the data structure of each block. The genesis follows a certain structure due to the implementation of PoP. Note that this step is specific and only if by the following steps can you create the genesis block. It is as follows:
It is a list of dictionary of
genesis = [{'plyrList': [...], 'winnerAddr': pubKey, 'matchData': x}, ...]
where:
- plyrList: a dictionary, the list (
[...]
) of players' public key of the match - winnerAddr: a byte value, the public key (
pubKey
) of the winner - matchData: any data type for you to manipulate (you need to define
winnerFunc
andratingFunc
later to pick the winner and rate the players respectively in your defined matchData structure
Then, assume you defined the structure above, do:
with open("genesis_block.data", "wb") as f:
f.write(pickle.dumps(genesis))
The genesis_block.data file is created, put the file into the genesis user config folder (this user is responsible to activate this new blockchain). The path is as follows:
- ./config/blockchain/ where the root is the place you ran the setup script for the genesis user.
Note that genesis block can be empty, so you can simply create an empty genesis
with the specific data structure above, and write into the genesis_block.data
file.
script with bootstrap
within the filename means it is setup for a bootstrap node, client
within the filename means it is setup for a client node
the two script demonstrate the setting up the directory running the script as a PoP project directory
the two script mainly demonstrate the process shown in the following image:
both script initialize the PoP object like this:
myPoP = PoP.handler(nodeID=nodeID, winnerFunc=myGetMVP.getMVP, ratingFunc=myGetRating.getRating)
where:
winnerFunc (for pop game verification):
- takes game result as function parameter in python standard data structure (i.e. winnerFunc(game_result))
- returns 'winner's public key' in public key data type (bytes, same as .pubKey in config directory) (a single winner)
ratingFunc (for pop blockchain):
- takes game result and a player's public key as function parameter (i.e. ratingFunc(game_result, player_public_key))
- returns a float value as 'rating'
- initialize parameters and PoP object
- main wrapper
- open a thread and run a function to start the pop blockchain
- start a pop match with a provided matchID, terminates after the game result verification completed
- set the global variable waitingMatch = False, so that the pop blockchain thread will returns the blockchain status
- blockchain thread terminates, the script exits
- run_match()
- use function decorator to start pop match
- bootstrap node waits for connection
- client node connect to bootstrap node
- import arbitrary game result into python standard data structure (1533081738_4035507616_match.data)
- verify game result
- node broadcast game result (only winner node can successfully broadcast the game result)
- use function decorator to start pop match
- run_blockchain() (sample_bootstrap.py only)
- return chain status after the match has been completed and broadcasted to bootstrap chain (since bootstrap is the winner)
the following 2 scripts assumed client script is opened shortly after bootstrap script (about 1 second)
auto_broadcast is set False in the PoP blockchain decorator to show specific blockchain operation example
matches are also generated for demo convenience
- run_blockchain()
- wait for client blockchain (Bob blockchain) connects
- generate 5 matches of Alice (this node) wins, this will write 2 blocks
- time.sleep(5) to wait for client blockchain operation
- broadcast the blockchain to other nodes (i.e. client blockchain)
- waiting for client blockchain (client script step 4) to replace this blockchain since client will add two more matches in its blockchain
- print the chain status and terminate
- run_blockchain()
- generate 2 matches of Bob (this node) wins, this will write 1 block
- waiting for bootstrap node to replace this blockchain, since it is 1 block ahead (bootstrap script step 4)
- after bootstrap blockchain has replaced, the 2 matches generated by Bob is not included, yet the 2 matches ratings exceeds the target, so it writes another block immediately (4th block)
- broadcast the blockchain to other nodes (i.e. bootstrap blockchain)
- print the chain status and terminate
- both rating function used in the blockchain, and winner function used in the game verification, should be mutually agreed (e.g. blockchain genesis block), but it is not in the blockchain now
- all of the entry port for both pop game and pop blockchain can be accessed by anyone, no signature verification required
- validation machine(s) of a match is needed (e.g. start and end time of a match is recorded, cheat detection is implemented etc), or anyone can forge a match and broadcast it
py2p disconnect() function doesn't work properly, so there is no safe disconnect feature in pop game