universum 0.1.2 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: e2c8f33d68ea490e3785c31d1cca9977af498602
4
- data.tar.gz: d7ac8121bc501b8339954fdc0c23111c4c5d60d8
3
+ metadata.gz: db4bf31c857f63ae6e203d9ddcdb718556c6f2a7
4
+ data.tar.gz: 3989ec1e3962f0768a8a3c108e72a76b4c4b969b
5
5
  SHA512:
6
- metadata.gz: fbcfc8ea96b55f557636649078b665554464b5009f411cc6208890a4b4f558a633198321d796093b0b1e0cfa31bd58154064d2112576258ffdbf4ed97b065687
7
- data.tar.gz: 03a36a8c12c2ff2e88789028b4c978c1ed3d60d909d773b1fb79592a9212b819e2712ce3e2dd82682b250d80b608c3d6cc61880ecadd589a1d14722c63f8c36d
6
+ metadata.gz: 276c1b77f06cf0e0dcb10a7a4ca4ef072365f1852c30e5b83279582f4d38447ad178c975c9e169e40aef5871a8d830cd8748d371c9d5846f3fd3211fe251ed07
7
+ data.tar.gz: 7086a5e4984497cc116ee05eb397a34afc7e766474e5aacc802421a37c16c5c4031936dae03fbdecd8b9172c5d990c52391dc3a18b14620d4ae92b26e46405e4
data/Manifest.txt CHANGED
@@ -4,14 +4,30 @@ Manifest.txt
4
4
  README.md
5
5
  Rakefile
6
6
  lib/universum.rb
7
+ lib/universum/account.rb
8
+ lib/universum/address.rb
9
+ lib/universum/contract.rb
7
10
  lib/universum/enum.rb
8
11
  lib/universum/event.rb
12
+ lib/universum/function.rb
13
+ lib/universum/receipt.rb
14
+ lib/universum/safe_array.rb
15
+ lib/universum/safe_hash.rb
16
+ lib/universum/transaction.rb
17
+ lib/universum/type.rb
18
+ lib/universum/units_money.rb
19
+ lib/universum/units_time.rb
9
20
  lib/universum/universum.rb
10
21
  lib/universum/version.rb
11
22
  test/contracts/greeter.rb
12
23
  test/contracts/mytoken.rb
13
24
  test/helper.rb
25
+ test/test_array.rb
14
26
  test/test_enum.rb
15
27
  test/test_event.rb
16
28
  test/test_greeter.rb
29
+ test/test_hash.rb
30
+ test/test_struct.rb
31
+ test/test_units_money.rb
32
+ test/test_units_time.rb
17
33
  test/test_version.rb
data/README.md CHANGED
@@ -1,4 +1,4 @@
1
- New to Universum? See the [Universum (World Computer) White Paper](https://github.com/openblockchains/universum/blob/master/WHITEPAPER.md)!
1
+ New to Universum? See the [Universum (World Computer) White Paper](https://github.com/s6ruby/universum/blob/master/WHITEPAPER.md)!
2
2
 
3
3
 
4
4
 
@@ -7,8 +7,8 @@ New to Universum? See the [Universum (World Computer) White Paper](https://githu
7
7
  next generation ethereum 2.0 world computer runtime - run contract scripts / transactions in plain vanilla / standard ruby on the blockchain - update the (contract-protected / isolated) world states with plain vanilla / standard SQL
8
8
 
9
9
 
10
- * home :: [github.com/openblockchains/universum](https://github.com/openblockchains/universum)
11
- * bugs :: [github.com/openblockchains/universum/issues](https://github.com/openblockchains/universum/issues)
10
+ * home :: [github.com/s6ruby/universum](https://github.com/s6ruby/universum)
11
+ * bugs :: [github.com/s6ruby/universum/issues](https://github.com/s6ruby/universum/issues)
12
12
  * gem :: [rubygems.org/gems/universum](https://rubygems.org/gems/universum)
13
13
  * rdoc :: [rubydoc.info/gems/universum](http://rubydoc.info/gems/universum)
14
14
 
@@ -56,21 +56,21 @@ contract Greeter is Mortal {
56
56
  and
57
57
 
58
58
  ``` ruby
59
- class Greeter < Contract
59
+ ##################
60
+ # Greeter Contract
60
61
 
61
- def initialize( greeting )
62
- @owner = msg.sender
63
- @greeting = greeting
64
- end
62
+ def initialize( greeting )
63
+ @owner = msg.sender
64
+ @greeting = greeting
65
+ end
65
66
 
66
- def greet
67
- @greeting
68
- end
67
+ def greet
68
+ @greeting
69
+ end
69
70
 
70
- def kill
71
- selfdestruct( msg.sender ) if msg.sender == @owner
72
- end
73
- end # class Greeter
71
+ def kill
72
+ selfdestruct( msg.sender ) if msg.sender == @owner
73
+ end
74
74
  ```
75
75
 
76
76
  (Source: [`contracts/greeter.rb`](test/contracts/greeter.rb))
@@ -82,18 +82,17 @@ And let's run the greeter with Universum (Uni):
82
82
  ``` ruby
83
83
  require 'universum'
84
84
 
85
- require_relative 'greeter'
86
-
87
-
88
85
  Account['0x1111'] ## setup a test account
89
86
 
90
- tx = Tx.send( from: '0x1111', data: [Greeter, 'Hello World!'] )
87
+ ## create contract (english version)
88
+ tx = Uni.send_transaction( from: '0x1111', data: ['./greeter', 'Hello World!'] )
91
89
  greeter = tx.receipt.contract
92
90
 
93
91
  puts greeter.greet
94
92
  #=> Hello World!
95
93
 
96
- tx = Tx.send( from: '0x1111', data: [Greeter, '¡Hola, mundo!'] )
94
+ ## create contract (spanish version)
95
+ tx = Uni.send_transaction( from: '0x1111', data: ['./greeter', '¡Hola, mundo!'] )
97
96
  greeter_es = Receipt[ tx ].contract
98
97
 
99
98
  puts greeter_es.greet
@@ -141,23 +140,23 @@ contract MyToken {
141
140
  and
142
141
 
143
142
  ``` ruby
144
- class MyToken < Contract
143
+ ############################
144
+ ## My Token Contract
145
145
 
146
- def initialize( initial_supply )
147
- @balance_of = Mapping.of( Address => Money )
148
- @balance_of[ msg.sender] = initial_supply
149
- end
146
+ def initialize( initial_supply )
147
+ @balance_of = Mapping.of( Address => Money )
148
+ @balance_of[ msg.sender] = initial_supply
149
+ end
150
150
 
151
- def transfer( to, value )
152
- assert( @balance_of[ msg.sender ] >= value )
153
- assert( @balance_of[ to ] + value >= @balance_of[ to ] )
151
+ def transfer( to, value )
152
+ assert @balance_of[ msg.sender ] >= value
153
+ assert @balance_of[ to ] + value >= @balance_of[ to ]
154
154
 
155
- @balance_of[ msg.sender ] -= value
156
- @balance_of[ to ] += value
155
+ @balance_of[ msg.sender ] -= value
156
+ @balance_of[ to ] += value
157
157
 
158
- true
159
- end
160
- end # class MyToken
158
+ true
159
+ end
161
160
  ```
162
161
 
163
162
  (Source: [`contracts/mytoken.rb`](test/contracts/mytoken.rb))
@@ -167,12 +166,12 @@ end # class MyToken
167
166
 
168
167
  ## More Contract Samples
169
168
 
170
- See the [`/universum-contracts`](https://github.com/openblockchains/universum-contracts) collection.
169
+ See the [`/universum-contracts`](https://github.com/s6ruby/universum-contracts) collection.
171
170
 
172
171
 
173
172
  ## More Documentation / Articles / Contracts
174
173
 
175
- [Programming Crypto Blockchain Contracts Step-by-Step Book / Guide](https://github.com/openblockchains/programming-cryptocontracts) - Let's Start with Ponzi & Pyramid Schemes. Run Your Own Lotteries, Gambling Casinos and more on the Blockchain World Computer...
174
+ [Programming Crypto Blockchain Contracts Step-by-Step Book / Guide](https://github.com/s6ruby/programming-cryptocontracts) - Let's Start with Ponzi & Pyramid Schemes. Run Your Own Lotteries, Gambling Casinos and more on the Blockchain World Computer...
176
175
 
177
176
 
178
177
 
data/Rakefile CHANGED
@@ -8,7 +8,7 @@ Hoe.spec 'universum' do
8
8
  self.summary = "universum - next generation ethereum 2.0 world computer runtime; run contract scripts / transactions in plain vanilla / standard ruby on the blockchain; update the (contract-protected / isolated) world states with plain vanilla / standard SQL"
9
9
  self.description = summary
10
10
 
11
- self.urls = ['https://github.com/openblockchains/universum']
11
+ self.urls = ['https://github.com/s6ruby/universum']
12
12
 
13
13
  self.author = 'Gerald Bauer'
14
14
  self.email = 'wwwmake@googlegroups.com'
data/lib/universum.rb CHANGED
@@ -4,14 +4,33 @@
4
4
  ## stdlibs
5
5
  require 'pp' ## pretty print (pp)
6
6
  require 'digest'
7
+ require 'date'
8
+ require 'time'
9
+ require 'uri'
10
+
7
11
 
8
12
 
9
13
  ## our own code
10
14
  require 'universum/version' # note: let version always go first
11
15
 
16
+ require 'universum/units_time'
17
+ require 'universum/units_money'
18
+
19
+ require 'universum/safe_array'
20
+ require 'universum/safe_hash'
21
+
12
22
  require 'universum/enum'
13
23
  require 'universum/event'
14
24
 
25
+ require 'universum/function'
26
+ require 'universum/address'
27
+ require 'universum/type'
28
+ require 'universum/account'
29
+ require 'universum/contract'
30
+ require 'universum/transaction'
31
+ require 'universum/receipt'
32
+
33
+
15
34
  require 'universum/universum'
16
35
 
17
36
 
@@ -0,0 +1,52 @@
1
+ # encoding: utf-8
2
+
3
+
4
+ class Account
5
+
6
+ @@directory = {}
7
+ def self.find_by_address( key )
8
+ ## clean key (allow "embedded" name e.g 0x1111 (Alice))
9
+ key = key.gsub(/\(.+\)/, '' ).strip
10
+ @@directory[ key ]
11
+ end
12
+ def self.find( key ) find_by_address( key ); end # make find_by_address the default finder
13
+ def self.at( key) find_by_address( key ); end # another "classic" alias for find_by_address
14
+
15
+ def self.[]( key )
16
+ o = find_by_address( key )
17
+ if o
18
+ o
19
+ else
20
+ o = new( key )
21
+ ## note: auto-register (new) address in (yellow page) directory
22
+ @@directory[ key ] = o
23
+ o
24
+ end
25
+ end
26
+
27
+ def self.all() @@directory.values; end
28
+
29
+
30
+ ####
31
+ # account (builtin) services / transaction methods
32
+ include Address ## includes address + send/transfer/balance
33
+
34
+ ## note: for now allow write access too!!!
35
+ def balance=( value )
36
+ @balance = value
37
+ end
38
+
39
+ attr_reader :tx
40
+ def _auto_inc_tx() @tx += 1; end ## "internal" method - (auto) increment transaction (tx) counter
41
+
42
+ ## note: needed by transfer/send
43
+ def this() Universum.this; end ## returns current contract
44
+
45
+ private
46
+ def initialize( address, balance: 0, tx: 0 )
47
+ @address = address # type address - (hex) string starts with 0x
48
+ @balance = balance # uint
49
+ @tx = tx # transaction (tx) count (used for nonce and replay attack protection)
50
+ end
51
+
52
+ end # class Account
@@ -0,0 +1,75 @@
1
+ # encoding: utf-8
2
+
3
+
4
+ #############
5
+ # FIX/FIX/FIX!!!! - turn Address into a class!!!!
6
+
7
+
8
+ module Address
9
+ def self.zero() '0x0000'; end
10
+
11
+ def address
12
+ if @address
13
+ @address
14
+ else
15
+ if is_a? Contract
16
+ ## fix/todo: use/lookup proper addr from contract
17
+ ## construct address for now from object_id
18
+ "0x#{(object_id << 1).to_s(16)}"
19
+ else ## assume Account
20
+ '0x0000'
21
+ end
22
+ end
23
+ end # method address
24
+
25
+ def transfer( value ) ## @payable @public
26
+ ## todo/fix: throw exception if insufficient funds
27
+ send( value ) # returns true/false
28
+ end
29
+
30
+ def send( value ) ## @payable @public
31
+ ## todo/fix: assert value > 0
32
+ ## todo/fix: add missing -= part in transfer!!!!
33
+
34
+ ## use this (current contract) for debit (-) ammount
35
+ this._sub( value ) # sub(tract) / debit from the sender (current contract)
36
+ _add( value ) # add / credit to the recipient
37
+ end
38
+
39
+ def balance
40
+ @balance ||= 0 ## return 0 if undefined
41
+ end
42
+
43
+ ### private (internal use only) methods - PLEASE do NOT use (use transfer/send)
44
+ def _sub( value )
45
+ @balance ||= 0 ## return 0 if undefined
46
+ @balance -= value
47
+ end
48
+
49
+ def _add( value )
50
+ @balance ||= 0 ## return 0 if undefined
51
+ @balance += value
52
+ end
53
+ end # module Address
54
+
55
+
56
+
57
+ class String
58
+ def transfer( value )
59
+ ## check if self is an address
60
+ if self.start_with?( '0x' )
61
+ Account[self].transfer( value )
62
+ else
63
+ raise "(Auto-)Type Conversion from Address (Hex) String to Account Failed; Expected String Starting with 0x got #{self}; Contract Halted (Stopped)"
64
+ end
65
+ end
66
+
67
+ def send( value )
68
+ ## check if self is an address
69
+ if self.start_with?( '0x' )
70
+ Account[self].send( value )
71
+ else
72
+ raise "(Auto-)Type Conversion from Address (Hex) String to Account Failed; Expected String Starting with 0x got #{self}; Contract Halted (Stopped)"
73
+ end
74
+ end
75
+ end
@@ -0,0 +1,87 @@
1
+ # encoding: utf-8
2
+
3
+
4
+ class Contract
5
+
6
+ #########
7
+ # load "class-less" contract
8
+ # e.g. SathoshiDice = Contract.load( './sathoshi_dice' )
9
+ def self.load( path )
10
+ extname = File.extname( path ) #=> ".rb"
11
+ if extname == '.rb'
12
+ ## do nothing
13
+ else
14
+ ## "convenience" helper - (auto-)add .rb extension
15
+ path = "#{path}.rb"
16
+ end
17
+
18
+ code = File.open( path, 'r:bom|utf-8' ) { |f| f.read }
19
+ klass = Class.new( Contract )
20
+ klass.class_eval( code ) ## note: use class_eval (NOT instance_eval)
21
+ klass
22
+ end
23
+
24
+
25
+ @@directory = {}
26
+ def self.find_by_address( key )
27
+ ## clean key (allow "embedded" class name e.g 0x4de2ee8 (SatoshiDice))
28
+ key = key.gsub(/\(.+\)/, '' ).strip
29
+ @@directory[ key ];
30
+ end
31
+ def self.find( key ) find_by_address( key ); end # make find_by_address the default finder
32
+ def self.at( key) find_by_address( key ); end # another "classic" alias for find_by_address
33
+ def self.[]( key ) find_by_address( key ); end
34
+
35
+ def self.store( key, o ) @@directory.store( key, o ); end ## store (add) new contract object (o) to hash / directory
36
+ def self.all() @@directory.values; end
37
+
38
+
39
+
40
+ ####
41
+ # account (builtin) services / transaction methods
42
+ include Address ## includes address + send/transfer/balance
43
+
44
+ ## function sig(nature) macro for types (dummy for now)
45
+ # e.g. use like
46
+ # payable :process
47
+ # payable :initialize
48
+ # payable :bet, Integer
49
+ # payable :lend_money, Address => Bool ## returns Bool
50
+ def self.payable( *args ); end
51
+
52
+ payable :receive
53
+
54
+ ####
55
+ # todo/double check: auto-add payable default fallback - why? why not?
56
+ def receive ## @payable default fallback - use different name - why? why not? (e.g. handle/process/etc.)
57
+ end
58
+
59
+
60
+ def assert( condition )
61
+ if condition == true
62
+ ## do nothing
63
+ else
64
+ raise 'Contract Assertion Failed; Contract Halted (Stopped)'
65
+ end
66
+ end
67
+
68
+
69
+ def this() Universum.this; end ## returns current contract
70
+ def log( event ) Universum.log( event ); end
71
+ def msg() Universum.msg; end
72
+ def block() Universum.block; end
73
+ def blockhash( number )
74
+ ## todo/fix: only allow going back 255 blocks; check if number is in range!!!
75
+ Universum.blockhash( number )
76
+ end
77
+
78
+ private
79
+ def selfdestruct( owner ) ## todo/check: use a different name e.g. destruct/ delete - why? why not?
80
+ ## selfdestruct function (for clean-up on blockchain)
81
+ owner.send( @balance ) ## send back all funds owned/hold by contract
82
+
83
+ ## fix: does nothing for now - add some code (e.g. cleanup)
84
+ ## mark as destruct - why? why not?
85
+ end
86
+
87
+ end # class Contract
@@ -0,0 +1,10 @@
1
+ # encoding: utf-8
2
+
3
+ ########################################
4
+ # builtin "global" functions
5
+
6
+ def sha256( *args )
7
+ ## note: allow multiple args (string)
8
+ ## all args will get auto-joined (with no padding)
9
+ Digest::SHA256.hexdigest( args.join )
10
+ end
@@ -0,0 +1,52 @@
1
+ # encoding: utf-8
2
+
3
+
4
+ class Receipt ## transaction receipt
5
+
6
+ @@directory = {}
7
+ def self.find( tx )
8
+ key = "#{tx.from}/#{tx.nonce}"
9
+ @@directory[ key ];
10
+ end
11
+ def self.[]( tx ) find( tx ); end
12
+
13
+ def self.store( o )
14
+ key = "#{o.from}/#{o.nonce}"
15
+ @@directory.store( key, o ); end ## store (add) new receipt object (o) to hash / directory
16
+ def self.all() @@directory.values; end
17
+
18
+
19
+ ## required attributes / fields
20
+ attr_reader :nonce, :from, :to, :value,
21
+ :block_number
22
+ ## optional
23
+ attr_reader :contract_address
24
+
25
+ def initialize( tx:,
26
+ block:,
27
+ contract: nil )
28
+ @nonce = tx.nonce
29
+ @from = tx.from
30
+ @to = tx.to
31
+ @value = tx.value
32
+ ## todo/fix: add data too!!!
33
+
34
+ @block_number = block.number
35
+ ## todo/fix: add block_hash
36
+
37
+ if contract
38
+ ## note: for easier debugging add class name in () to address (needs to get stripped away in lookup)
39
+ @contract_address = "#{contract.address} (#{contract.class.name})"
40
+ else
41
+ @contract_address = nil
42
+ end
43
+ end
44
+
45
+ def contract # convenience helper (quick contract lookup)
46
+ if @contract_address
47
+ Contract.find( @contract_address )
48
+ else
49
+ nil
50
+ end
51
+ end
52
+ end