Skip to content

Commit

Permalink
add ledger lite
Browse files Browse the repository at this point in the history
  • Loading branch information
geraldb committed Nov 1, 2020
1 parent bedaa63 commit 35fe33b
Show file tree
Hide file tree
Showing 16 changed files with 1,187 additions and 1 deletion.
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@ Gems:

- [blockchain-lite](blockchain-lite) - build your own blockchain with crypto hashes - revolutionize the world with blockchains, blockchains, blockchains one block at a time
- [merkletree](merkletree) - build your own crypto hash trees; named after Ralph Merkle who patented hash trees in 1979 (the patent expired in 2002); grow your own money on trees
- [ledger-lite](ledger-lite) - hyper ledger book for the distributed blockchain internet era; add your transactions one block at a time; transfer crypto(currencie)s and balance the accounts






Expand Down
50 changes: 50 additions & 0 deletions ledger-lite/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
*.gem
*.rbc
/.config
/coverage/
/InstalledFiles
/pkg/
/spec/reports/
/spec/examples.txt
/test/tmp/
/test/version_tmp/
/tmp/

# Used by dotenv library to load environment variables.
# .env

## Specific to RubyMotion:
.dat*
.repl_history
build/
*.bridgesupport
build-iPhoneOS/
build-iPhoneSimulator/

## Specific to RubyMotion (use of CocoaPods):
#
# We recommend against adding the Pods directory to your .gitignore. However
# you should judge for yourself, the pros and cons are mentioned at:
# https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
#
# vendor/Pods/

## Documentation cache and generated files:
/.yardoc/
/_yardoc/
/doc/
/rdoc/

## Environment normalization:
/.bundle/
/vendor/bundle
/lib/bundler/man/

# for a library or gem, you might want to ignore these files since the code is
# intended to run in multiple environments; otherwise, check them in:
# Gemfile.lock
# .ruby-version
# .ruby-gemset

# unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
.rvmrc
3 changes: 3 additions & 0 deletions ledger-lite/HISTORY.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
### 0.0.1 / 2018-01-02

* Everything is new. First release
13 changes: 13 additions & 0 deletions ledger-lite/Manifest.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
HISTORY.md
LICENSE.md
Manifest.txt
README.md
Rakefile
lib/ledger-lite.rb
lib/ledger-lite/base.rb
lib/ledger-lite/version.rb
test/helper.rb
test/test_blocks.rb
test/test_transactions.rb
test/test_transactions_v2.rb
test/test_version.rb
4 changes: 4 additions & 0 deletions ledger-lite/NOTES.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# Notes


## Todos
310 changes: 310 additions & 0 deletions ledger-lite/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,310 @@
# Ledger Lite

ledger-lite library / gem - hyper ledger book for the distributed blockchain internet era; add your transactions one block at a time; transfer crypto(currencie)s and balance the accounts


* home :: [github.com/openblockchains/ledger.lite.rb](https://github.com/openblockchains/ledger.lite.rb)
* bugs :: [github.com/openblockchains/ledger.lite.rb/issues](https://github.com/openblockchains/ledger.lite.rb/issues)
* gem :: [rubygems.org/gems/ledger-lite](https://rubygems.org/gems/ledger-lite)
* rdoc :: [rubydoc.info/gems/ledger-lite](http://rubydoc.info/gems/ledger-lite)



## Usage

Let's add some transactions to the (hyper) ledger book:

| From | To | $ |
|---------------------------|--------------|----:|
| Central Bank (†) | Vincent | 11 |
| Vincent | Anne | 3 |
| Anne | Julia | 2 |
| Julia | Luuk | 1 |
| | | |
| De Nederlandsche Bank (†) | Ruben | 11 |
| Vincent | Max | 3 |
| Ruben | Julia | 2 |
| Anne | Martijn | 1 |

(†): Mining Transaction - New Dutch Gulden ($) on the Market!



### Use `send` (send payment/transfer money)

```ruby

ledger = Ledger.new

ledger.send( "Central Bank†", "Vincent", 11 )
ledger.send( "Vincent", "Anne", 3 )
ledger.send( "Anne", "Julia", 2 )
ledger.send( "Julia", "Luuk", 1 )

ledger.send( "De Nederlandsche Bank†", "Ruben", 11 )
ledger.send( "Vincent", "Max", 3 )
ledger.send( "Ruben", "Julia", 2 )
ledger.send( "Anne", "Martijn", 1 )

pp ledger ## pp = pretty print

```

resulting in

```
#<LedgerLite::Ledger
@addr={
"Vincent" => 5,
"Anne" => 0,
"Julia" => 3,
"Luuk" => 1,
"Ruben" => 9,
"Max" => 3,
"Martijn" => 1}>
```

that is, the addr hash holds all addresses (addr) with the account balances
telling you who owns how much:

| Addr(ess) | Balance $ |
|---------------------|----------:|
| Vincent | 5 |
| Anne | 0 |
| Julia | 3 |
| Luuk | 1 |
| Ruben | 9 |
| Max | 3 |
| Martijn | 1 |


### Use `write` to write / add transactions


Or use transaction hashes:

``` ruby
ledger = Ledger.new

ledger.write( from: "Central Bank†", to: "Vincent", amount: 11 )
ledger.write( from: "Vincent", to: "Anne", amount: 3 )
ledger.write( from: "Anne", to: "Julia", amount: 2 )
ledger.write( from: "Julia", to: "Luuk", amount: 1 )

ledger.write( { from: "De Nederlandsche Bank†", to: "Ruben", amount: 11 },
{ from: "Vincent", to: "Max", amount: 3 },
{ from: "Ruben", to: "Julia", amount: 2 },
{ from: "Anne", to: "Martijn", amount: 1 } )

pp ledger
```

Or use transaction (tx) classes/structs:

``` ruby
ledger = Ledger.new

ledger.write( Tx.new( "Central Bank†", "Vincent", 11 ))
ledger.write( Tx.new( "Vincent", "Anne", 3 ))
ledger.write( Tx.new( "Anne", "Julia", 2 ))
ledger.write( Tx.new( "Julia", "Luuk", 1 ))

ledger.write( Tx.new( "De Nederlandsche Bank†", "Ruben", 11 ),
Tx.new( "Vincent", "Max", 3 ),
Tx.new( "Ruben", "Julia", 2 ),
Tx.new( "Anne", "Martijn", 1 ))

pp ledger
```

Or use the operator `<<` alias for `write`:

```ruby
ledger = Ledger.new

ledger << Tx.new( "Central Bank†", "Vincent", 11 )
ledger << Tx.new( "Vincent", "Anne", 3 )
ledger << Tx.new( "Anne", "Julia", 2 )
ledger << Tx.new( "Julia", "Luuk", 1 )

ledger << [Tx.new( "De Nederlandsche Bank†", "Ruben", 11 ),
Tx.new( "Vincent", "Max", 3 ),
Tx.new( "Ruben", "Julia", 2 ),
Tx.new( "Anne", "Martijn", 1 )]

pp ledger
```


Or use blocks of transaction hashes:

``` ruby

ledger = Ledger.new

ledger.write( Block.new( { from: "Central Bank†", to: "Vincent", amount: 11 },
{ from: "Vincent", to: "Anne", amount: 3 },
{ from: "Anne", to: "Julia", amount: 2 },
{ from: "Julia", to: "Luuk", amount: 1 } ),
Block.new( { from: "De Nederlandsche Bank†", to: "Ruben", amount: 11 },
{ from: "Vincent", to: "Max", amount: 3 },
{ from: "Ruben", to: "Julia", amount: 2 },
{ from: "Anne", to: "Martijn", amount: 1 } ))

pp ledger
```


Or use blocks of transaction classes/structs:

``` ruby
ledger = Ledger.new

ledger.write( Block.new( Tx.new( "Central Bank†", "Vincent", 11 ),
Tx.new( "Vincent", "Anne", 3 ),
Tx.new( "Anne", "Julia", 2 ),
Tx.new( "Julia", "Luuk", 1 )),
Block.new( Tx.new( "De Nederlandsche Bank†", "Ruben", 11 ),
Tx.new( "Vincent", "Max", 3 ),
Tx.new( "Ruben", "Julia", 2 ),
Tx.new( "Anne", "Martijn", 1 )))

pp ledger
```

Or use blocks of transaction classes/structs (with keyword arguments):

```ruby
ledger = Ledger.new

ledger.write( Block.new( Tx.new( from: "Central Bank†", to: "Vincent", amount: 11 ),
Tx.new( from: "Vincent", to: "Anne", amount: 3 ),
Tx.new( from: "Anne", to: "Julia", amount: 2 ),
Tx.new( from: "Julia", to: "Luuk", amount: 1 )),
Block.new( Tx.new( from: "De Nederlandsche Bank†", to: "Ruben", amount: 11 ),
Tx.new( from: "Vincent", to: "Max", amount: 3 ),
Tx.new( from: "Ruben", to: "Julia", amount: 2 ),
Tx.new( from: "Anne", to: "Martijn", amount: 1 )))

pp ledger
```

# Bonus: Track Commodities, Collectibles or Assets

Ledger Lite lets you design / create your own transactions. For example, let's use
`from`, `to`, `qty` (quantity) and `name` (of commodity, collectible or asset).
Override the `Ledger#unpack` method for "unpacking" arguments from transactions
and the `Ledger#send` method for "committing" transactions:


``` ruby
def unpack( tx )
## "unpack" from, to, qty, name values
if tx.is_a?( Hash ) ## support hashes
from = tx[:from]
to = tx[:to]
qty = tx[:qty]
name = tx[:name]
else ## assume it's a transaction (tx) struct/class
from = tx.from
to = tx.to
qty = tx.qty
name = tx.name
end
[from,to,qty,name]
end
```

and

``` ruby
def send( from, to, qty, name )
if sufficient?( from, qty, name )
if self.class.config.coinbase?( from )
# note: coinbase has unlimited supply!! magic happens here
else
@addr[ from ][ name ] -= qty
end
@addr[ to ] ||= {} ## make sure addr exists (e.g. init with empty hash {})
@addr[ to ][ name ] ||= 0
@addr[ to ][ name ] += qty
end
end
```

Now use the ledger with the new transaction format like:


``` ruby
ledger = Ledger.new

ledger.send( "Keukenhof†", "Vincent", 11, "Tulip Admiral van Eijck" )
ledger.send( "Vincent", "Anne", 3, "Tulip Admiral van Eijck" )
ledger.send( "Anne", "Julia", 2, "Tulip Admiral van Eijck" )
ledger.send( "Julia", "Luuk", 1, "Tulip Admiral van Eijck" )

ledger.send( "Dutchgrown†", "Ruben", 11, "Tulip Semper Augustus" )
ledger.send( "Vincent", "Max", 3, "Tulip Admiral van Eijck" )
ledger.send( "Ruben", "Julia", 2, "Tulip Semper Augustus" )
ledger.send( "Anne", "Martijn", 1, "Tulip Admiral van Eijck" )

pp ledger ## pp == pretty print
```

resulting in:

```
#<LedgerLite::Ledger
@addr={
"Vincent" => {"Tulip Admiral van Eijck" => 5},
"Anne" => {"Tulip Admiral van Eijck" => 0},
"Julia" => {"Tulip Admiral van Eijck" => 1, "Tulip Semper Augustus" => 2},
"Luuk" => {"Tulip Admiral van Eijck" => 1},
"Ruben" => {"Tulip Semper Augustus" => 9},
"Max" => {"Tulip Admiral van Eijck" => 3},
"Martijn" => {"Tulip Admiral van Eijck" => 1}}>
```

Or use blocks of transaction classes/structs (with keyword arguments):


``` ruby
ledger = Ledger.new

ledger.write( Block.new( Tx.new( from: "Keukenhof†", to: "Vincent", qty: 11, name: "Tulip Admiral van Eijck" ),
Tx.new( from: "Vincent", to: "Anne", qty: 3, name: "Tulip Admiral van Eijck" ),
Tx.new( from: "Anne", to: "Julia", qty: 2, name: "Tulip Admiral van Eijck" ),
Tx.new( from: "Julia", to: "Luuk", qty: 1, name: "Tulip Admiral van Eijck" )),
Block.new( Tx.new( from: "Dutchgrown†", to: "Ruben", qty: 11, name: "Tulip Semper Augustus" ),
Tx.new( from: "Vincent", to: "Max", qty: 3, name: "Tulip Admiral van Eijck" ),
Tx.new( from: "Ruben", to: "Julia", qty: 2, name: "Tulip Semper Augustus" ),
Tx.new( from: "Anne", to: "Martijn", qty: 1, name: "Tulip Admiral van Eijck" )))

pp ledger
```

And so on and on.




## Ledger Lite in the Real World

- [**centralbank**](https://github.com/openblockchains/centralbank) - command line tool (and core library) - print your own money / cryptocurrency; run your own federated central bank nodes on the blockchain peer-to-peer over HTTP; revolutionize the world one block at a time
- [**tulipmania**](https://github.com/openblockchains/tulipmania) - command line tool (and core library) - tulips on the blockchain; learn by example from the real world (anno 1637) - buy! sell! hodl! enjoy the beauty of admiral of admirals, semper augustus, and more; run your own hyper ledger tulip exchange nodes on the blockchain peer-to-peer over HTTP; revolutionize the world one block at a time
- [**shilling**](https://github.com/bitshilling/bitshilling.tools) - command line tool (and core library) - shilling (or schilling) on the blockchain! rock-solid alpine dollar from austria; print (mine) your own shillings; run your own federated shilling central bank nodes w/ public distributed (hyper) ledger book on the blockchain peer-to-peer over HTTP; revolutionize the world one block at a time
- You? Add your tool / service



## References

[**Programming Cryptocurrencies and Blockchains (in Ruby)**](http://yukimotopress.github.io/blockchains) by Gerald Bauer et al, 2018, Yuki & Moto Press


## License

![](https://publicdomainworks.github.io/buttons/zero88x31.png)

The `ledger-lite` scripts are dedicated to the public domain.
Use it as you please with no restrictions whatsoever.
Loading

0 comments on commit 35fe33b

Please sign in to comment.