This is a read-only snapshot of the ComputerCraft forums, taken in April 2020.
pauliuskas05's profile picture

Computercraft Virtual Currency

Started by pauliuskas05, 05 July 2014 - 01:42 PM
pauliuskas05 #1
Posted 05 July 2014 - 03:42 PM
Hi, I am a noob on ComputerCraft. I really want to make a Virtual Currency on my server. So that it use floppy disks as Credit Cards, but only keep account name in them. Everything else (password, balance) would be on a server computer.
AssossaGPB #2
Posted 05 July 2014 - 05:45 PM
Well, if your new to ComputerCraft and Lua I would NOT recommend a virtual currency system as your first project. First, go read some tutorials on Lua, and some on the ComputerCraft apis. Then, you should make some simple programs and learn rednet. But, if you think your ready then read on:

First, you'll want to have some encryption system. I recommend using my [topic='19328']Encryption Api[/topic] for the key exchange and [topic='42']StrUtils[/topic] for the actual encryption.
Next, you want to set up a packet protocol, this involves parsing rednet messages and doing the corresponding action.
Finally, you want to make sure you hash your passwords when sending them to the server for extra security.

That's all there is to it, kinda complicated, but kinda simple with the right apis. If you need anymore help, I check the forums twice a day and am often on the irc, just shout my name!

PS: I don't recommend using disks for credit cards as they can easily be cloned.
pauliuskas05 #3
Posted 05 July 2014 - 05:59 PM
PS: I don't recommend using disks for credit cards as they can easily be cloned.

Why not ? On them there is going to be only account name that can only be accessed with password.
AssossaGPB #4
Posted 06 July 2014 - 01:16 AM
PS: I don't recommend using disks for credit cards as they can easily be cloned.

Why not ? On them there is going to be only account name that can only be accessed with password.
Oh, ok. I thought you were gonna store the password on the card as well.
TheOddByte #5
Posted 06 July 2014 - 01:18 AM
PS: I don't recommend using disks for credit cards as they can easily be cloned.

Why not ? On them there is going to be only account name that can only be accessed with password.
Oh, ok. I thought you were gonna store the password on the card as well.
Well if he was going to then he could hash them :P/>
Bomb Bloke #6
Posted 06 July 2014 - 02:19 AM
It's easy enough to copy a disk's contents. It's nearly impossible to clone a disk's ID number. There doesn't need to be anything on a disk at all if you purely want to use it for identification - in fact, done properly, use of disks would also negate any need to even ask for a password… So long as the disks themselves aren't stealable…
AssossaGPB #7
Posted 06 July 2014 - 02:52 AM
PS: I don't recommend using disks for credit cards as they can easily be cloned.

Why not ? On them there is going to be only account name that can only be accessed with password.
Oh, ok. I thought you were gonna store the password on the card as well.
Well if he was going to then he could hash them :P/>
But then someone could just copy the hash

It's easy enough to copy a disk's contents. It's nearly impossible to clone a disk's ID number. There doesn't need to be anything on a disk at all if you purely want to use it for identification - in fact, done properly, use of disks would also negate any need to even ask for a password… So long as the disks themselves aren't stealable…
Hm, never thought of that, how do you read the disk's id from the computer?
theoriginalbit #8
Posted 06 July 2014 - 03:30 AM
Well if you do it right, it doesn't matter if people can see the hash, 'cause they need to enter the password, not the hashed password.

Take a look into the Disk API for how to get info about disks.
AlkamlBan #9
Posted 07 July 2014 - 04:30 PM
This (in my opinion at least) is a great idea. A currency that can be used in computercraft servers! Finally we will have something else to try and hack other than computers! Just kiddin (not really) but I think it is a great idea!
pauliuskas05 #10
Posted 07 July 2014 - 09:50 PM
I writed some code, but it doesn't seems to work. When I will get home i will post it…
Edited on 07 July 2014 - 07:53 PM
AlkamlBan #11
Posted 08 July 2014 - 10:07 AM
I writed some code, but it doesn't seems to work. When I will get home i will post it…

I worked on something aswell but it also didn't seem to work. Well…I will check it out today after all I wrote the program in 2am yesterday so I couldn't make out any mistakes in the code
AlkamlBan #12
Posted 08 July 2014 - 10:25 AM
The problem with this is that there can be a big freakin' problem. What will happen if someone kills you and steals your "credit card"? Well one possibility would be to make checks every now and then. So for example every fifth purchase you ask the user to input his code or else they block the card. Also checks can be make where the server has a countdown. Once the countdown is over for the next purchase the user needs his code. There is a problem with both…First with the first one the thief would go to a store and buy a lot of things all in once and it would be on you to pay them! The second idea also has a problem because the thief can buy anything he wants before the check is up. But supposing you are not in a hardcore server (so you don't get kicked when you die) the user of the card can go to the bank and say that his card was stolen so they can instantly block it the point is that the thief is still given some time to buy whatever he wants. So…I guess that we will have to find a way of tightening security
pauliuskas05 #13
Posted 09 July 2014 - 10:55 AM
ATM Code:

local modem_side = "back"
local server = 6
local d_side = "bottom"
local pin_check = nil
local exists = nil
function cls()
term.clear()
term.setCursorPos(1,1)
print("BANK")
term.setCursorPos(1,2)
end
function dej()
disk.eject(d_side)
end
rednet.open(modem_side)
cls()
print("		 Please insert your Credit Card")
local event, isDisk = os.pullEvent("disk")
if fs.exists("disk/bank") then
local ccid = disk.getID(d_side)
rednet.send(server, ccid)
senderId, exists, distance= rednet.receive()
if exists == "yes" then
  cls()
  write("		   PIN: ")
  local pin = read("*")
  rednet.send(server, pin)
  senderId, pin_check, distance = rednet.receive()
   if pin_check == "good" then
    pin = nil
    pin_check = nil
    senderId, money, distance = rednet.receive()
    print("You have: "..money)
   elseif pin_check == "bad" then
    cls()
    print("Wrong PIN !")
   end
elseif exists == "no" then
  cls()
  print("	  Account doesn't exists")
end
else
cls()
print("		 This is not a credit card")
dej()
sleep(1.5)
os.shutdown()
end

Server Code:

term.clear()
term.setCursorPos(1,1)
local modem_side = "top"
local srv_id = os.getComputerID()
print("Running BANK server on "..srv_id)
rednet.open(modem_side)
while true do
senderId, id, distance = rednet.receive()
if fs.exists("acc/"..id) then
rednet.send(senderId, "yes")
config.load("acc",id)
local real_pass = config.readVal("pass")
senderId, pass, distance = rednet.receive()
  if pass == real_pass then
   rednet.send(senderId, "good")
   local money = config.readVal("money")
   rednet.send(senderId, money)
   break
  elseif pass ~= real_pass then
   rednet.send(senderId, "bad")
   break
  end
else
  rednet.send(senderId, "no")
  break
end
end


On ATM I get Error
startup:23: attempt to call nil

Help me !

EDIT:
BTW I am using "Config API' by ben657
Edited on 09 July 2014 - 08:56 PM
AlkamlBan #14
Posted 09 July 2014 - 01:12 PM
ATM Code:

local modem_side = "back"
local server = 6
local d_side = "bottom"
local pin_check = nil
local exists = nil
function cls()
term.clear()
term.setCursorPos(1,1)
print("BANK")
term.setCursorPos(1,2)
end
function dej()
disk.eject(d_side)
end
rednet.open(modem_side)
cls()
print("		 Please insert your Credit Card")
local event, isDisk = os.pullEvent("disk")
if fs.exists("disk/bank") then
local ccid = disk.getID(d_side)
rednet.send(server, ccid)
senderId, exists, distance= rednet.receive()
if exists == "yes" then
  cls()
  write("		   PIN: ")
  local pin = read("*")
  rednet.send(server, pin)
  senderId, pin_check, distance = rednet.receive()
   if pin_check == "good" then
	pin = nil
	pin_check = nil
	senderId, money, distance = rednet.receive()
	print("You have: "..money)
   elseif pin_check == "bad" then
	cls()
	print("Wrong PIN !")
   end
elseif exists == "no" then
  cls()
  print("	  Account doesn't exists")
end
else
cls()
print("		 This is not a credit card")
dej()
sleep(1.5)
os.shutdown()
end

Server Code:

term.clear()
term.setCursorPos(1,1)
local modem_side = "top"
local srv_id = os.getComputerID()
print("Running BANK server on "..srv_id)
rednet.open(modem_side)
while true do
senderId, id, distance = rednet.receive()
if fs.exists("acc/"..id) then
rednet.send(senderId, "yes")
config.load("acc",id)
local real_pass = config.readVal("pass")
senderId, pass, distance = rednet.receive()
  if pass == real_pass then
   rednet.send(senderId, "good")
   local money = config.readVal("money")
   rednet.send(senderId, money)
   break
  elseif pass ~= real_pass then
   rednet.send(senderId, "bad")
   break
  end
else
  rednet.send(senderId, "no")
  break
end
end


On ATM I get Error
startup:23: attempt to call nil

Help me !

Your code is…HUGE (no offence). Btw I am really close to completing it and it reaquires a lot less code(well I did it slightly differently but I also get nearly the same erroe :(/>
pauliuskas05 #15
Posted 11 July 2014 - 08:34 PM
Anybody ? I have no idea what causes this error…
flaghacker #16
Posted 11 July 2014 - 08:46 PM
Which of your 2 programs errors? The ATM or the server? Also, read this for common errors and how to fix them: http://www.computercraft.info/forums2/index.php?/topic/14531-read-this-post-before-asking-questions/#common_errors
Edited on 11 July 2014 - 06:48 PM
AlkamlBan #17
Posted 11 July 2014 - 10:55 PM
All right. Here you go! Got it working:
Bank Server Code:

rednet.open("right")
cards = {{1, 1000}, {2, 550}}
while true do
senderId, ID = rednet.receive("id")
for i = 1, #cards do
    if cards[i][1] == ID then
	    rednet.send(22, "yes", "answer")
	    senderId, amount = rednet.receive("pay")
	    if cards[i][2] >= amount then
		    rednet.send(22, "done", "transaction")
		    cards[i][2] = cards[i][2] - amount
	    else
		    rednet.send(22, "nope", "transaction")
	    end
    else
	    rednet.send(22, "noCustomer", "transaction")
    end
end
end  

And here is the code for the counter of the store:

diskID = disk.getID("bottom")
amount = 100
rednet.open("right")
rednet.send(23, diskID, "id")
repeat
    senderId, message = rednet.receive("answer")
until senderId == 23
if message == "yes" then
    rednet.send(23, amount, "pay")
    senderId, message = rednet.receive("transaction")
    if senderId == 23 and message == "done" then
	    print("Transaction Complete!")
    elseif senderId == 23 and message == "nope" then
	    print("Transaction Failed: Not enough money")
    else
	    print("No such customer")
    end
end

This is how it works:
1)The computer in the store sends a mesage to the bank server containing the cards ID.
2)The server checks in its table to see if the first number of the tables inside the table match the ID
3)If they do the server sends a message to the computer telling it to send it the amount
4)The computer checks the amount and sees if the second number inside the table the ID was found is bigger or equal to the amount
5)If it is it subtracts the amount from the money in the bank and sends a message to the computer saying that the transaction has been completed.

I will do ATMs tommorow (its already 1am :D/> ) and post the code
AlkamlBan #18
Posted 11 July 2014 - 11:03 PM
I will do ATMs tommorow (its already 1am :D/> ) and post the code

Actually I won't because ATMs dispence virtual currency as real-life money. I don't see the point in making such a thing (I mean its more about redstone thatn computers). Plus why use solid money when you can access your bank account from anywhere? Not that a hacker can't steal your money this way but if you carry real money the thief that will kill you can steal it and you can't retreave it but with this you can go to the bank and report you stolen card and they will stop all transactions happening using that specific card. Plus while an ATM dispences money a guy sitting close can easily pick up some. Both ways have an enemy. So its your call which you will use. If you want I will make an ATM just ask.
pauliuskas05 #19
Posted 15 July 2014 - 09:40 AM
I will do ATMs tommorow (its already 1am :D/>/>/> ) and post the code

Actually I won't because ATMs dispence virtual currency as real-life money. I don't see the point in making such a thing (I mean its more about redstone thatn computers). Plus why use solid money when you can access your bank account from anywhere? Not that a hacker can't steal your money this way but if you carry real money the thief that will kill you can steal it and you can't retreave it but with this you can go to the bank and report you stolen card and they will stop all transactions happening using that specific card. Plus while an ATM dispences money a guy sitting close can easily pick up some. Both ways have an enemy. So its your call which you will use. If you want I will make an ATM just ask.

It's only VIRTAUL, so there is no cash to give out.

EDIT:
BTW I am on vacation. So I won't always be online.
Edited on 15 July 2014 - 07:44 AM
AlkamlBan #20
Posted 15 July 2014 - 11:09 AM
I will do ATMs tommorow (its already 1am :D/>/>/> ) and post the code

Actually I won't because ATMs dispence virtual currency as real-life money. I don't see the point in making such a thing (I mean its more about redstone thatn computers). Plus why use solid money when you can access your bank account from anywhere? Not that a hacker can't steal your money this way but if you carry real money the thief that will kill you can steal it and you can't retreave it but with this you can go to the bank and report you stolen card and they will stop all transactions happening using that specific card. Plus while an ATM dispences money a guy sitting close can easily pick up some. Both ways have an enemy. So its your call which you will use. If you want I will make an ATM just ask.

It's only VIRTAUL, so there is no cash to give out.

EDIT:
BTW I am on vacation. So I won't always be online.

Yes but it would be nice wouldn't it? and btw hackers can do some cool tricks to steal you money from the bank. As I said you are not safe in any of the two ways so its your call. I guess having both would be the best option :)/>
hilburn #21
Posted 15 July 2014 - 03:11 PM
By the way, using a PIM to stand on (OpenPeripherals) when you insert your credit card would allow you to verify the user with PIM.inventoryName() as well as allow you to interact directly with the players inventory, allowing him to withdraw "cash" or deposit into his account without the risk entailed with dispensers
pauliuskas05 #22
Posted 16 July 2014 - 09:42 PM
Bank Server Code:

rednet.open("right")
cards = {{1, 1000}, {2, 550}}
while true do
senderId, ID = rednet.receive("id")
for i = 1, #cards do
    if cards[i][1] == ID then
	    rednet.send(22, "yes", "answer")
	    senderId, amount = rednet.receive("pay")
	    if cards[i][2] >= amount then
		    rednet.send(22, "done", "transaction")
		    cards[i][2] = cards[i][2] - amount
	    else
		    rednet.send(22, "nope", "transaction")
	    end
    else
	    rednet.send(22, "noCustomer", "transaction")
    end
end
end  


Well, this code is very good, but is there a way to load bank accounts from file ?
Because I need a way to edit and create accounts easily. With program or just using edit…
Edited on 17 July 2014 - 08:05 AM
pauliuskas05 #23
Posted 18 July 2014 - 08:35 AM
Bank Server Code:

rednet.open("right")
cards = {{1, 1000}, {2, 550}}
while true do
senderId, ID = rednet.receive("id")
for i = 1, #cards do
    if cards[i][1] == ID then
	    rednet.send(22, "yes", "answer")
	    senderId, amount = rednet.receive("pay")
	    if cards[i][2] >= amount then
		    rednet.send(22, "done", "transaction")
		    cards[i][2] = cards[i][2] - amount
	    else
		    rednet.send(22, "nope", "transaction")
	    end
    else
	    rednet.send(22, "noCustomer", "transaction")
    end
end
end  

And here is the code for the counter of the store:

diskID = disk.getID("bottom")
amount = 100
rednet.open("right")
rednet.send(23, diskID, "id")
repeat
    senderId, message = rednet.receive("answer")
until senderId == 23
if message == "yes" then
    rednet.send(23, amount, "pay")
    senderId, message = rednet.receive("transaction")
    if senderId == 23 and message == "done" then
	    print("Transaction Complete!")
    elseif senderId == 23 and message == "nope" then
	    print("Transaction Failed: Not enough money")
    else
	    print("No such customer")
    end
end

This is how it works:
1)The computer in the store sends a mesage to the bank server containing the cards ID.
2)The server checks in its table to see if the first number of the tables inside the table match the ID
3)If they do the server sends a message to the computer telling it to send it the amount
4)The computer checks the amount and sees if the second number inside the table the ID was found is bigger or equal to the amount
5)If it is it subtracts the amount from the money in the bank and sends a message to the computer saying that the transaction has been completed.
But this isn't secure. Because there is no PIN, so anyone who has your card can access it. :(/>
AlkamlBan #24
Posted 27 July 2014 - 08:09 PM
Bank Server Code:

rednet.open("right")
cards = {{1, 1000}, {2, 550}}
while true do
senderId, ID = rednet.receive("id")
for i = 1, #cards do
	if cards[i][1] == ID then
		rednet.send(22, "yes", "answer")
		senderId, amount = rednet.receive("pay")
		if cards[i][2] >= amount then
			rednet.send(22, "done", "transaction")
			cards[i][2] = cards[i][2] - amount
		else
			rednet.send(22, "nope", "transaction")
		end
	else
		rednet.send(22, "noCustomer", "transaction")
	end
end
end  

And here is the code for the counter of the store:

diskID = disk.getID("bottom")
amount = 100
rednet.open("right")
rednet.send(23, diskID, "id")
repeat
	senderId, message = rednet.receive("answer")
until senderId == 23
if message == "yes" then
	rednet.send(23, amount, "pay")
	senderId, message = rednet.receive("transaction")
	if senderId == 23 and message == "done" then
		print("Transaction Complete!")
	elseif senderId == 23 and message == "nope" then
		print("Transaction Failed: Not enough money")
	else
		print("No such customer")
	end
end

This is how it works:
1)The computer in the store sends a mesage to the bank server containing the cards ID.
2)The server checks in its table to see if the first number of the tables inside the table match the ID
3)If they do the server sends a message to the computer telling it to send it the amount
4)The computer checks the amount and sees if the second number inside the table the ID was found is bigger or equal to the amount
5)If it is it subtracts the amount from the money in the bank and sends a message to the computer saying that the transaction has been completed.
But this isn't secure. Because there is no PIN, so anyone who has your card can access it. :(/>

Yea I know but really I mean why can't we give those hackers something to do?
pauliuskas05 #25
Posted 28 July 2014 - 08:43 PM
Bank Server Code:

rednet.open("right")
cards = {{1, 1000}, {2, 550}}
while true do
senderId, ID = rednet.receive("id")
for i = 1, #cards do
	if cards[i][1] == ID then
		rednet.send(22, "yes", "answer")
		senderId, amount = rednet.receive("pay")
		if cards[i][2] >= amount then
			rednet.send(22, "done", "transaction")
			cards[i][2] = cards[i][2] - amount
		else
			rednet.send(22, "nope", "transaction")
		end
	else
		rednet.send(22, "noCustomer", "transaction")
	end
end
end  

And here is the code for the counter of the store:

diskID = disk.getID("bottom")
amount = 100
rednet.open("right")
rednet.send(23, diskID, "id")
repeat
	senderId, message = rednet.receive("answer")
until senderId == 23
if message == "yes" then
	rednet.send(23, amount, "pay")
	senderId, message = rednet.receive("transaction")
	if senderId == 23 and message == "done" then
		print("Transaction Complete!")
	elseif senderId == 23 and message == "nope" then
		print("Transaction Failed: Not enough money")
	else
		print("No such customer")
	end
end

This is how it works:
1)The computer in the store sends a mesage to the bank server containing the cards ID.
2)The server checks in its table to see if the first number of the tables inside the table match the ID
3)If they do the server sends a message to the computer telling it to send it the amount
4)The computer checks the amount and sees if the second number inside the table the ID was found is bigger or equal to the amount
5)If it is it subtracts the amount from the money in the bank and sends a message to the computer saying that the transaction has been completed.
But this isn't secure. Because there is no PIN, so anyone who has your card can access it. :(/>/>

Yea I know but really I mean why can't we give those hackers something to do?
I could make PINs myself, but I don't know how to use tables and assign them to a Credit Card(ID)…
AlkamlBan #26
Posted 30 July 2014 - 02:33 PM
Bank Server Code:

rednet.open("right")
cards = {{1, 1000}, {2, 550}}
while true do
senderId, ID = rednet.receive("id")
for i = 1, #cards do
	if cards[i][1] == ID then
		rednet.send(22, "yes", "answer")
		senderId, amount = rednet.receive("pay")
		if cards[i][2] >= amount then
			rednet.send(22, "done", "transaction")
			cards[i][2] = cards[i][2] - amount
		else
			rednet.send(22, "nope", "transaction")
		end
	else
		rednet.send(22, "noCustomer", "transaction")
	end
end
end  

And here is the code for the counter of the store:

diskID = disk.getID("bottom")
amount = 100
rednet.open("right")
rednet.send(23, diskID, "id")
repeat
	senderId, message = rednet.receive("answer")
until senderId == 23
if message == "yes" then
	rednet.send(23, amount, "pay")
	senderId, message = rednet.receive("transaction")
	if senderId == 23 and message == "done" then
		print("Transaction Complete!")
	elseif senderId == 23 and message == "nope" then
		print("Transaction Failed: Not enough money")
	else
		print("No such customer")
	end
end

This is how it works:
1)The computer in the store sends a mesage to the bank server containing the cards ID.
2)The server checks in its table to see if the first number of the tables inside the table match the ID
3)If they do the server sends a message to the computer telling it to send it the amount
4)The computer checks the amount and sees if the second number inside the table the ID was found is bigger or equal to the amount
5)If it is it subtracts the amount from the money in the bank and sends a message to the computer saying that the transaction has been completed.
But this isn't secure. Because there is no PIN, so anyone who has your card can access it. :(/>/>

Yea I know but really I mean why can't we give those hackers something to do?
I could make PINs myself, but I don't know how to use tables and assign them to a Credit Card(ID)…

PIN isn't hard to make just go to the server and at the table add for each an extra string (PIN) inside each table (eg {1, 1000, "1234"}). The you need to modify the counter code to take a string and send it along with the rest of thi information to the bank server (make sure the bank server receives it). Finally and an if statement in the bank server before the if cards[2] >= amount etc etc stating the following:

if cards[i][3] == <variable in which the ping from the counter is> then
   <if cards[i][2] >= amount in here>
else
  rednet.send(id, "nope") <you may need to modify this>
end
pauliuskas05 #27
Posted 30 July 2014 - 06:25 PM
PIN isn't hard to make just go to the server and at the table add for each an extra string (PIN) inside each table (eg {1, 1000, "1234"}). The you need to modify the counter code to take a string and send it along with the rest of thi information to the bank server (make sure the bank server receives it). Finally and an if statement in the bank server before the if cards[2] >= amount etc etc stating the following:

if cards[i][3] == <variable in which the ping from the counter is> then
   <if cards[i][2] >= amount in here>
else
  rednet.send(id, "nope") <you may need to modify this>
end
Thanks! I will test it later.
AlkamlBan #28
Posted 02 August 2014 - 09:40 PM
The reason I didn't put a PIN in the original code is because a PIN need to be added by the user as a result it takes a bit of time to do so. So with that in mind if a server hosts multiple stores for example that use the PIN method if someone is sending a request to the server while someone else is entering the ping the server will not accept it because it will wait for a different kind of message. As a result it will be as if the card isn't valid even though it is. What you can do though is that you set up a "mini-server" under each store where data will be picked up and sent one by one. Maybe each server communicates with each other? Anyway its up to you. But you will basically need to set each request in an order and send them 1 by 1 to the server so that the transactions happen correctly.
Darkitech #29
Posted 18 August 2014 - 03:27 AM
Why not just set up an encryption system at the tellers, if someone tried to change or duplicate the card, they won't know how to I am currently working on one right now….. But the duplication problem I am sorta having troubles stopping…..