Blockchain Wallet

Overview

The blockchain keeps a “distributed ledger” (DLT) but has no information on who can update the ledger data.

This project has two parts: one is the server which executes commands to process transactions (creates transactions and writes it to the blockchain / retrieves transactions from the blockchain); and the other is the client which sends requests to the server to complete tasks such as checking the balance, sending funds to another account, listing accounts and etc.

Set up

If this is your first time running go, you will need to set the GOPATH.

Dependencies

At the root directory, run

go get ./

to download the dependencies. To make sure everything is properly set up, run

make test

at the root directory. If it passes all the tests, you are ready to go!

To Start the Server

The server is a HTTP server. At the root directory, you can simply run the falling script to start the server:

make run_server

You will want to run this in it’s own window as it runs until it is killed or until you send it a shutdown message.

To Call the Server from the Client.

At the root directory, you can simply run the following script to start the client:

make run_client

Then go to ./client folder, you can run the ./client as follows:

Usage: ./client [ --cfg file ] [ --host URL ] [ --cmd Command ] [ --from Acct ] [ --to Acct ] [ --amount #### ] [ --addr Addr ] [ --password <PW> ]
Command can be:
  send-funds-to --from MyAcct --to AcctTo --amount ####
  list-accts
  list-wallet
  list-my-keys
  acct-value --acct Acct
  new-key-file --password <PW>
  acct-value --acct Acct
  shutdown-server --addr address --password <PW>
  validate-signed-message --addr address
  server-status

Demo

After you run make run_server, the ./server/main/run_server.sh would create a genesis block and some accounts with initial balances, and processes some transactions.

Blockchain Wallet Demo

./server/run_server:

go build

account0=0x7e3afec048bc7be745d0fa0f5af97d3978c40e9a
account1=0xb0d533a8064ed180967aa4dafa453deab107961c
account2=0x31568cc92115a2ebe6eb37e9a7c7f6334b988196
account3=0x4e27d9c8ba3a6904f7a7cb31eae5ccce8bf33300

rm ./data/*

# crate the genesis block
echo "\nCreate genesis block:"
./main --create-genesis

# test whether the block chain is successfully created
echo "\nCheck whether the genesis block has been created:"
./main --test-read-block

# list accounts available on the block chain
echo "\nList accounts on the block chain:"
./main --list-accounts

# check the balance for accounts before several transactions
echo "\nCheck the balances for some accounts:"
./main --show-balance $account0
./main --show-balance $account1
./main --show-balance $account2
./main --show-balance $account3

# test sending funds
echo "\nTransactions between some accounts:"
./main --test-send-funds $account0 $account1 500 x x x x
./main --test-send-funds $account0 $account2 500 x x x x
./main --test-send-funds $account0 $account3 500 x x x x

# check the balance for accounts after several transactions
echo "\nCheck the balances for the above accounts:"
./main --show-balance $account0
./main --show-balance $account1
./main --show-balance $account2
./main --show-balance $account3

# start the server at 127.0.0.1:9191
echo "\nStart the server at 127.0.0.1:9191:"
./main --server 127.0.0.1:9191

Here is the output:

( cd server/main ; ./run_server.sh)

Create genesis block:
((Mining)) Hash for Block [0543ce00776885535a69f621fd1b3a174d3a916c55b074d9414b15af0f3269b2] nonce [       0]
((Mining)) Hash for Block [0543ce00776885535a69f621fd1b3a174d3a916c55b074d9414b15af0f3269b2] nonce [       0]

Check whether the genesis block has been created:
You must run "create-genesis" first before this test.

List accounts on the block chain:

List of Addresses
	0x0c34a1a3c5ae302cb41f9cfd999e7950b8ebf40f
	0xe7b8a518bf1b5c4f01b2a7ee39a2800a982e06ee
	0x31568cc92115a2ebe6eb37e9a7c7f6334b988196
	0x5ae7b3cf64adc3d7fef099319a9be4acb8bd73ed
	0xb0d533a8064ed180967aa4dafa453deab107961c
	0x42f487a6d5c86962310d5ab5afe5cad7bc80805b
	0x40681739b0ef568acce20f5575ad4cf24223926f
	0x6e06bf940bb57ade69cb03153d1c3842411bd3c1
	0x885765a2fcfb72e68d82d656c6411b7d27bacdd7
	0x4af64cd87a47aab7cffdbada6bfd6aef47036c03
	0x4e27d9c8ba3a6904f7a7cb31eae5ccce8bf33300
	0xdb180da9a8982c7bb75ca40039f959cb959c62e8
	0x7e3afec048bc7be745d0fa0f5af97d3978c40e9a
	0x9d41e5938767466af28865e1c33071f1561d57a8
	0x3b65b88e4256c8926358551072f17460efe5452b

Check the balances for some accounts:
Acct: 0x7e3afec048bc7be745d0fa0f5af97d3978c40e9a Value: 500000
Acct: 0xb0d533a8064ed180967aa4dafa453deab107961c Value: 500000
Acct: 0x31568cc92115a2ebe6eb37e9a7c7f6334b988196 Value: 500000
Acct: 0x4e27d9c8ba3a6904f7a7cb31eae5ccce8bf33300 Value: 500000

Transactions between some accounts:

Before sending funds the balances for 0x7e3afec048bc7be745d0fa0f5af97d3978c40e9a and 0xb0d533a8064ed180967aa4dafa453deab107961c are as follows:
Acct: 0xb0d533a8064ed180967aa4dafa453deab107961c Value: 500000
Acct: 0x7e3afec048bc7be745d0fa0f5af97d3978c40e9a Value: 500000
Sent 0xb0d533a8064ed180967aa4dafa453deab107961c $500 from 0x7e3afec048bc7be745d0fa0f5af97d3978c40e9a
((Mining)) Hash for Block [001a443254bbf24ca1cb60f06f909a40cc01ea6942dbce0a474b241f9876d3d6] nonce [       3]

Before sending funds the balances for 0x7e3afec048bc7be745d0fa0f5af97d3978c40e9a and 0x31568cc92115a2ebe6eb37e9a7c7f6334b988196 are as follows:
Acct: 0x31568cc92115a2ebe6eb37e9a7c7f6334b988196 Value: 500000
Acct: 0x7e3afec048bc7be745d0fa0f5af97d3978c40e9a Value: 499500
Sent 0x31568cc92115a2ebe6eb37e9a7c7f6334b988196 $500 from 0x7e3afec048bc7be745d0fa0f5af97d3978c40e9a
((Mining)) Hash for Block [0fb66d13d109ab4cbd87f184e30915ad43e65e0423383d559a669d88af550122] nonce [      11]

Before sending funds the balances for 0x7e3afec048bc7be745d0fa0f5af97d3978c40e9a and 0x4e27d9c8ba3a6904f7a7cb31eae5ccce8bf33300 are as follows:
Acct: 0x4e27d9c8ba3a6904f7a7cb31eae5ccce8bf33300 Value: 500000
Acct: 0x7e3afec048bc7be745d0fa0f5af97d3978c40e9a Value: 499000
Sent 0x4e27d9c8ba3a6904f7a7cb31eae5ccce8bf33300 $500 from 0x7e3afec048bc7be745d0fa0f5af97d3978c40e9a
((Mining)) Hash for Block [043b518a9a5ae00b872040df7d22848769e207a48ca3a261a001849379e3e138] nonce [      41]

Check the balances for the above accounts:
Acct: 0x7e3afec048bc7be745d0fa0f5af97d3978c40e9a Value: 498500
Acct: 0xb0d533a8064ed180967aa4dafa453deab107961c Value: 500500
Acct: 0x31568cc92115a2ebe6eb37e9a7c7f6334b988196 Value: 500500
Acct: 0x4e27d9c8ba3a6904f7a7cb31eae5ccce8bf33300 Value: 500500

Then it would start the server at http://localhost:9191 and listen to the client. Next, running make run_client is actually calling ./client/run_client.sh, which creates some transactions or requests to the server.

run_client.sh:

go build

password=123456
loginAccount=0x7e3afec048bc7be745d0fa0f5af97d3978c40e9a
account1=0xb0d533a8064ed180967aa4dafa453deab107961c
account2=0x31568cc92115a2ebe6eb37e9a7c7f6334b988196
account3=0x4e27d9c8ba3a6904f7a7cb31eae5ccce8bf33300

if [[ -d wallet-data ]]; then
    rm -rf wallet-data
else
    make -p wallet-data
fi

# test call
./client --cmd echo

# list accounts available on server
echo "\nList accounts on the server:"
./client --cmd list-accts

# check the server status
echo "\nCheck server status:"
./client --cmd server-status

# generate 1 key pair and store it
echo "\nGenerate one key pair and store it:"
./client --cmd new-key-file --password $password
addressOfKeyfile=$(./client --cmd list-my-keys)

# check the balance of several accounts
echo "\nCheck balance:"
./client --cmd acct-value --acct $loginAccount
./client --cmd acct-value --acct $account1
./client --cmd acct-value --acct $account2
./client --cmd acct-value --acct $account3

# validate the signed message
echo "\nValidate the signed message:"
./client --cmd validate-signed-message --addr $addressOfKeyfile --password $password

# test of send funds to
echo "\nSend \$1000 from $loginAccount to $account1:"
./client --cmd send-funds-to --from $loginAccount --to $account1 --amount 1000 --memo dinner --addr $addressOfKeyfile --password $password
echo "\nSend \$1500 from $loginAccount to $account2:"
./client --cmd send-funds-to --from $loginAccount --to $account2 --amount 1500 --memo dinner --addr $addressOfKeyfile --password $password
echo "\nSend \$2500 from $loginAccount to $account3:"
./client --cmd send-funds-to --from $loginAccount --to $account3 --amount 2500 --memo dinner --addr $addressOfKeyfile --password $password

# check the balance of accounts
echo "\nCheck balance:"
./client --cmd acct-value --acct $loginAccount
./client --cmd acct-value --acct $account1
./client --cmd acct-value --acct $account2
./client --cmd acct-value --acct $account3

# shut down the server
./client --cmd shutdown-server --addr $addressOfKeyfile --password $password

The Output on the Server Side

Before sending funds the balances for 0x7e3afec048bc7be745d0fa0f5af97d3978c40e9a and 0xb0d533a8064ed180967aa4dafa453deab107961c are as follows:
Acct: 0xb0d533a8064ed180967aa4dafa453deab107961c Value: 500500
Acct: 0x7e3afec048bc7be745d0fa0f5af97d3978c40e9a Value: 498500
Sent 0xb0d533a8064ed180967aa4dafa453deab107961c $1000 from 0x7e3afec048bc7be745d0fa0f5af97d3978c40e9a
((Mining)) Hash for Block [0fcbcae92e1dbc85576d9d38ac8816a6904c6b508d13e688c696bebd5492a74f] nonce [       0]

Before sending funds the balances for 0x7e3afec048bc7be745d0fa0f5af97d3978c40e9a and 0x31568cc92115a2ebe6eb37e9a7c7f6334b988196 are as follows:
Acct: 0x31568cc92115a2ebe6eb37e9a7c7f6334b988196 Value: 500500
Acct: 0x7e3afec048bc7be745d0fa0f5af97d3978c40e9a Value: 497500
Sent 0x31568cc92115a2ebe6eb37e9a7c7f6334b988196 $1500 from 0x7e3afec048bc7be745d0fa0f5af97d3978c40e9a
((Mining)) Hash for Block [0f4d1bd72a6f8797c151c9071105f701717639b582401b2e91d208a6c9f509da] nonce [      13]

Before sending funds the balances for 0x7e3afec048bc7be745d0fa0f5af97d3978c40e9a and 0x4e27d9c8ba3a6904f7a7cb31eae5ccce8bf33300 are as follows:
Acct: 0x4e27d9c8ba3a6904f7a7cb31eae5ccce8bf33300 Value: 500500
Acct: 0x7e3afec048bc7be745d0fa0f5af97d3978c40e9a Value: 496000
Sent 0x4e27d9c8ba3a6904f7a7cb31eae5ccce8bf33300 $2500 from 0x7e3afec048bc7be745d0fa0f5af97d3978c40e9a
((Mining)) Hash for Block [099919cb7ab58d459c86ab7a61dfe739258bb8e35b1c275703c0b8c18a643cf1] nonce [      18]
Shutdown Now

The Output on the Client Side

( cd client ; ./run_client.sh)
Echo was called

List accounts on the server:
Body: [
	"0xb0d533a8064ed180967aa4dafa453deab107961c",
	"0x3b65b88e4256c8926358551072f17460efe5452b",
	"0x31568cc92115a2ebe6eb37e9a7c7f6334b988196",
	"0xdb180da9a8982c7bb75ca40039f959cb959c62e8",
	"0x5ae7b3cf64adc3d7fef099319a9be4acb8bd73ed",
	"0x885765a2fcfb72e68d82d656c6411b7d27bacdd7",
	"0x9d41e5938767466af28865e1c33071f1561d57a8",
	"0x40681739b0ef568acce20f5575ad4cf24223926f",
	"0x4af64cd87a47aab7cffdbada6bfd6aef47036c03",
	"0xe7b8a518bf1b5c4f01b2a7ee39a2800a982e06ee",
	"0x6e06bf940bb57ade69cb03153d1c3842411bd3c1",
	"0x7e3afec048bc7be745d0fa0f5af97d3978c40e9a",
	"0x0c34a1a3c5ae302cb41f9cfd999e7950b8ebf40f",
	"0x4e27d9c8ba3a6904f7a7cb31eae5ccce8bf33300",
	"0x42f487a6d5c86962310d5ab5afe5cad7bc80805b"
]

Check server status:
Body: {"status":"success","name":"go-server version 1.0.0","URI":"/api/status","req":Error:json: unsupported type: func() (io.ReadCloser, error), "response_header":{
	"Content-Type": [
		"application/json"
	]
}}

Generate one key pair and store it:
Address: 0x79fc57A68387aCeB79f0bb610F751eDFE04bF7C2
File Name: wallet-data/UTC--2020-01-21T03-21-11.338725Z--79fc57A68387aCeB79f0bb610F751eDFE04bF7C2

Check balance:
Body: { "status":"success", "acct": "0x7e3afec048bc7be745d0fa0f5af97d3978c40e9a"
  "value": 498500 }

Body: { "status":"success", "acct": "0xb0d533a8064ed180967aa4dafa453deab107961c"
  "value": 500500 }

Body: { "status":"success", "acct": "0x31568cc92115a2ebe6eb37e9a7c7f6334b988196"
  "value": 500500 }

Body: { "status":"success", "acct": "0x4e27d9c8ba3a6904f7a7cb31eae5ccce8bf33300"
  "value": 500500 }


Validate the signed message:
Match of Addr [79fc57A68387aCeB79f0bb610F751eDFE04bF7C2] to fn [UTC--2020-01-21T03-21-11.338725Z--79fc57A68387aCeB79f0bb610F751eDFE04bF7C2]
Body: {"status":"success","msg":"Signature validated"}


Send $1000 from 0x7e3afec048bc7be745d0fa0f5af97d3978c40e9a to 0xb0d533a8064ed180967aa4dafa453deab107961c:
Match of Addr [79fc57A68387aCeB79f0bb610F751eDFE04bF7C2] to fn [UTC--2020-01-21T03-21-11.338725Z--79fc57A68387aCeB79f0bb610F751eDFE04bF7C2]
http://0x7e3aFEc048bC7be745d0fA0F5af97D3978C40E9A:[email protected]:9191/api/send-funds-to
Body: {"status":"success", "blockNo":4 }

Send $1500 from 0x7e3afec048bc7be745d0fa0f5af97d3978c40e9a to 0x31568cc92115a2ebe6eb37e9a7c7f6334b988196:
Match of Addr [79fc57A68387aCeB79f0bb610F751eDFE04bF7C2] to fn [UTC--2020-01-21T03-21-11.338725Z--79fc57A68387aCeB79f0bb610F751eDFE04bF7C2]
http://0x7e3aFEc048bC7be745d0fA0F5af97D3978C40E9A:[email protected]:9191/api/send-funds-to
Body: {"status":"success", "blockNo":5 }

Send $2500 from 0x7e3afec048bc7be745d0fa0f5af97d3978c40e9a to 0x4e27d9c8ba3a6904f7a7cb31eae5ccce8bf33300:
Match of Addr [79fc57A68387aCeB79f0bb610F751eDFE04bF7C2] to fn [UTC--2020-01-21T03-21-11.338725Z--79fc57A68387aCeB79f0bb610F751eDFE04bF7C2]
http://0x7e3aFEc048bC7be745d0fA0F5af97D3978C40E9A:[email protected]:9191/api/send-funds-to
Body: {"status":"success", "blockNo":6 }

Check balance:
Body: { "status":"success", "acct": "0x7e3afec048bc7be745d0fa0f5af97d3978c40e9a"
  "value": 493500 }

Body: { "status":"success", "acct": "0xb0d533a8064ed180967aa4dafa453deab107961c"
  "value": 501500 }

Body: { "status":"success", "acct": "0x31568cc92115a2ebe6eb37e9a7c7f6334b988196"
  "value": 502000 }

Body: { "status":"success", "acct": "0x4e27d9c8ba3a6904f7a7cb31eae5ccce8bf33300"
  "value": 503000 }

Match of Addr [79fc57A68387aCeB79f0bb610F751eDFE04bF7C2] to fn [UTC--2020-01-21T03-21-11.338725Z--79fc57A68387aCeB79f0bb610F751eDFE04bF7C2]
Error: 500