Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
YottaChain
YTBP
提交
c5dba14c
Y
YTBP
项目概览
YottaChain
/
YTBP
通知
0
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
Y
YTBP
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
c5dba14c
编写于
7月 11, 2017
作者:
D
Daniel Larimer
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Refine EOS standard C++ library
- implement a large part of example exchange contract
上级
ba222004
变更
14
隐藏空白更改
内联
并排
Showing
14 changed file
with
974 addition
and
802 deletion
+974
-802
CMakeLists.txt
CMakeLists.txt
+1
-1
contracts/currency/Makefile
contracts/currency/Makefile
+3
-2
contracts/currency/currency.cpp
contracts/currency/currency.cpp
+2
-2
contracts/currency/currency.hpp
contracts/currency/currency.hpp
+1
-1
contracts/currency/currency.wast.hpp
contracts/currency/currency.wast.hpp
+130
-763
contracts/eoslib/eos.hpp
contracts/eoslib/eos.hpp
+375
-0
contracts/exchange/Makefile
contracts/exchange/Makefile
+19
-0
contracts/exchange/exchange.cpp
contracts/exchange/exchange.cpp
+226
-33
libraries/chain/include/eos/chain/key_value_object.hpp
libraries/chain/include/eos/chain/key_value_object.hpp
+42
-0
libraries/chain/include/eos/chain/message_handling_contexts.hpp
...ies/chain/include/eos/chain/message_handling_contexts.hpp
+12
-0
libraries/chain/include/eos/chain/types.hpp
libraries/chain/include/eos/chain/types.hpp
+3
-0
libraries/chain/message_handling_contexts.cpp
libraries/chain/message_handling_contexts.cpp
+74
-0
libraries/types/include/eos/types/native.hpp
libraries/types/include/eos/types/native.hpp
+1
-0
tests/tests/block_tests.cpp
tests/tests/block_tests.cpp
+85
-0
未找到文件。
CMakeLists.txt
浏览文件 @
c5dba14c
...
...
@@ -8,7 +8,7 @@ INCLUDE( VersionMacros )
INCLUDE
(
SetupTargetMacros
)
set
(
BLOCKCHAIN_NAME
"Eos"
)
set
(
CMAKE_CXX_STANDARD 1
4
)
set
(
CMAKE_CXX_STANDARD 1
7
)
set
(
CLI_CLIENT_EXECUTABLE_NAME eos_client
)
set
(
GUI_CLIENT_EXECUTABLE_NAME eos
)
...
...
contracts/currency/Makefile
浏览文件 @
c5dba14c
currency.wast
:
currency.cpp Makefile eos.hpp currency.hpp
/usr/local/Cellar/llvm/4.0.0_1/bin/clang-4.0
-emit-llvm
--std
=
c++14
--target
=
wasm32
-nostdinc
-c
currency.cpp
-I
..
-fno-threadsafe-statics
-fno-rtti
-fno-exceptions
-o
.currency.bc
currency.wast
:
currency.cpp Makefile
../eoslib/
eos.hpp currency.hpp
/usr/local/Cellar/llvm/4.0.0_1/bin/clang-4.0
-emit-llvm
-O3
--std
=
c++14
--target
=
wasm32
-c
currency.cpp
-I
..
-fno-threadsafe-statics
-fno-rtti
-fno-exceptions
-o
.currency.bc
-I
/usr/local/Cellar/llvm/4.0.0_1/include/c++/v1/
/Users/dlarimer/Downloads/llvm/build/bin/llc
-asm-verbose
=
false
.currency.bc
/Users/dlarimer/eos/libraries/binaryen/bin/s2wasm
-s
1024 .currency.s
>
currency.wast
wc
-l
currency.wast
...
...
@@ -9,6 +9,7 @@ currency.wast: currency.cpp Makefile eos.hpp currency.hpp
echo
')=====";'
>>
currency.wast.hpp
# /usr/local/Cellar/llvm/4.0.0_1/bin/clang-4.0 -emit-llvm -O3 --std=c++14 --target=wasm32 -nostdinc -c currency.cpp -I.. -fno-threadsafe-statics -fno-rtti -fno-exceptions -o .currency.bc
# /usr/local/Cellar/llvm/4.0.0_1/bin/clang-4.0 -emit-llvm --std=c++14 --target=wasm32 -nostdinc -c currency.cpp -I.. -fno-threadsafe-statics -fno-rtti -fno-exceptions -o .currency.bc
test.wast
:
test.cpp Makefile eos.hpp
/usr/local/Cellar/llvm/4.0.0_1/bin/clang-4.0
-emit-llvm
-O3
--std
=
c++14
--target
=
wasm32
-nostdinc
-c
test.cpp
-I
..
-fno-threadsafe-statics
-fno-rtti
-fno-exceptions
...
...
contracts/currency/currency.cpp
浏览文件 @
c5dba14c
...
...
@@ -25,8 +25,8 @@ void apply_currency_transfer() {
requireNotice
(
transfer
.
to
,
transfer
.
from
);
requireAuth
(
transfer
.
from
);
static
CurrencyAccount
from_account
;
static
CurrencyAccount
to_account
;
CurrencyAccount
from_account
;
CurrencyAccount
to_account
;
Db
::
get
(
transfer
.
from
,
NAME
(
"account"
),
from_account
);
Db
::
get
(
transfer
.
to
,
NAME
(
"account"
),
to_account
);
...
...
contracts/currency/currency.hpp
浏览文件 @
c5dba14c
#include
"eos.hpp"
#include
<eoslib/eos.hpp>
/**
* Transfer requires that the sender and receiver be the first two
...
...
contracts/currency/currency.wast.hpp
浏览文件 @
c5dba14c
...
...
@@ -18,325 +18,199 @@ const char* currency_wast = R"=====(
(import "env" "store_i64" (func $store_i64 (param i64 i64 i64 i32 i32) (result i32)))
(table 0 anyfunc)
(memory $0 1)
(data (i32.const 4) "
P
\04\00\00")
(data (i32.const
48
) "insufficient funds\00")
(data (i32.const 4) "
0
\04\00\00")
(data (i32.const
16
) "insufficient funds\00")
(export "memory" (memory $0))
(export "_Z23apply_currency_transferv" (func $_Z23apply_currency_transferv))
(export "init" (func $init))
(export "apply" (func $apply))
(func $_Z23apply_currency_transferv
(local $0 i32)
(local $1 i32)
(local $2 i64)
(local $3 i64)
(local $4 i32)
(local $0 i64)
(local $1 i64)
(local $2 i32)
(i32.store offset=4
(i32.const 0)
(tee_local $
4
(tee_local $
2
(i32.sub
(i32.load offset=4
(i32.const 0)
)
(i32.const
112
)
(i32.const
48
)
)
)
)
(call $_Z14currentMessageI8TransferET_v
(i32.add
(get_local $4)
(i32.const 80)
)
(i64.store offset=40
(get_local $2)
(i64.const 0)
)
(i32.store offset=108
(get_local $4)
(i32.add
(get_local $4)
(i32.const 80)
(drop
(call $readMessage
(i32.add
(get_local $2)
(i32.const 24)
)
(i32.const 24)
)
)
(call $_Z13requireNoticeIJyEEvyDpT_
(i64.load offset=88
(get_local $4)
)
(i64.load offset=80
(get_local $4)
(set_local $0
(i64.load offset=24
(get_local $2)
)
)
(call $requireAuth
(i64.load
(i32.load offset=108
(get_local $4)
)
(call $requireNotice
(i64.load offset=32
(get_local $2)
)
)
(block $label$0
(br_if $label$0
(i32.load8_u offset=24
(i32.const 0)
)
)
(drop
(call $_ZN15CurrencyAccountC2Ey
(i32.const 16)
(i64.const 0)
)
)
(i32.store8 offset=24
(i32.const 0)
(i32.const 1)
)
(call $requireNotice
(get_local $0)
)
(block $label$1
(br_if $label$1
(i32.load8_u offset=40
(i32.const 0)
)
)
(drop
(call $_ZN15CurrencyAccountC2Ey
(i32.const 32)
(i64.const 0)
)
)
(i32.store8 offset=40
(i32.const 0)
(i32.const 1)
(call $requireAuth
(i64.load offset=24
(get_local $2)
)
)
(set_local $0
(call $_ZN4NameC2Ey
(i32.add
(get_local $4)
(i32.const 72)
)
(i64.load
(i32.load offset=108
(get_local $4)
)
)
)
(i64.store offset=16
(get_local $2)
(i64.const 0)
)
(set_local $1
(call $_ZN4NameC2Ey
(i32.add
(get_local $4)
(i32.const 64)
)
(call $_ZN9ConstNameILy21967113313EE5valueEv)
)
(i64.store offset=8
(get_local $2)
(i64.const 0)
)
(drop
(call $_ZN2Db3getI15CurrencyAccountEEb4NameS2_RT_
(i64.load
(get_local $0)
)
(i64.load
(get_local $1)
)
(i32.const 16)
)
)
(set_local $0
(call $_ZN4NameC2Ey
(i32.add
(get_local $4)
(i32.const 56)
)
(i64.load offset=8
(i32.load offset=108
(get_local $4)
)
(call $load_i64
(i64.load offset=24
(get_local $2)
)
)
)
(set_local $1
(call $_ZN4NameC2Ey
(call $currentCode)
(i64.const 497826380083)
(i64.const 21967113313)
(i32.add
(get_local $
4
)
(i32.const
48
)
(get_local $
2
)
(i32.const
16
)
)
(
call $_ZN9ConstNameILy21967113313EE5valueEv
)
(
i32.const 8
)
)
)
(drop
(call $
_ZN2Db3getI15CurrencyAccountEEb4NameS2_RT_
(i64.load
(get_local $
0
)
(call $
load_i64
(i64.load
offset=32
(get_local $
2
)
)
(i64.load
(get_local $1)
(call $currentCode)
(i64.const 497826380083)
(i64.const 21967113313)
(i32.add
(get_local $2)
(i32.const 8)
)
(i32.const
32
)
(i32.const
8
)
)
)
(call $assert
(i64.ge_u
(i64.load offset=16
(
i32.const 0
)
(
get_local $2
)
)
(i64.load offset=16
(i32.load offset=108
(get_local $4)
)
(i64.load offset=40
(get_local $2)
)
)
(i32.const
48
)
(i32.const
16
)
)
(i64.store offset=16
(
i32.const 0
)
(tee_local $
3
(
get_local $2
)
(tee_local $
1
(i64.sub
(i64.load offset=16
(
i32.const 0
)
(
get_local $2
)
)
(tee_local $2
(i64.load offset=16
(i32.load offset=108
(get_local $4)
)
(tee_local $0
(i64.load offset=40
(get_local $2)
)
)
)
)
)
(i64.store offset=
32
(
i32.const 0
)
(i64.store offset=
8
(
get_local $2
)
(i64.add
(get_local $
2
)
(i64.load offset=
32
(
i32.const 0
)
(get_local $
0
)
(i64.load offset=
8
(
get_local $2
)
)
)
)
(block $label$2
(block $label$3
(br_if $label$3
(set_local $0
(i64.load offset=24
(get_local $2)
)
)
(block $label$0
(block $label$1
(br_if $label$1
(i64.eq
(get_local $
3
)
(get_local $
1
)
(i64.const 0)
)
)
(set_local $0
(call $_ZN4NameC2Ey
(i32.add
(get_local $4)
(i32.const 24)
)
(i64.load
(i32.load offset=108
(get_local $4)
)
)
)
)
(set_local $1
(call $_ZN4NameC2Ey
(drop
(call $store_i64
(get_local $0)
(i64.const 497826380083)
(i64.const 21967113313)
(i32.add
(get_local $
4
)
(get_local $
2
)
(i32.const 16)
)
(call $_ZN9ConstNameILy21967113313EE5valueEv)
)
)
(drop
(call $_ZN2Db5storeI15CurrencyAccountEEl4NameS2_RKT_
(i64.load
(get_local $0)
)
(i64.load
(get_local $1)
)
(i32.const 16)
)
)
(br $label$2)
)
(set_local $0
(call $_ZN4NameC2Ey
(i32.add
(get_local $4)
(i32.const 40)
)
(i64.load
(i32.load offset=108
(get_local $4)
)
)
)
)
(set_local $1
(call $_ZN4NameC2Ey
(i32.add
(get_local $4)
(i32.const 32)
(i32.const 8)
)
(call $_ZN9ConstNameILy21967113313EE5valueEv)
)
(br $label$0)
)
(drop
(call $_ZN2Db6removeI15CurrencyAccountEEb4NameS2_
(i64.load
(get_local $0)
)
(i64.load
(get_local $1)
)
)
)
)
(set_local $0
(call $_ZN4NameC2Ey
(i32.add
(get_local $4)
(i32.const 8)
)
(i64.load offset=8
(i32.load offset=108
(get_local $4)
)
(call $remove_i64
(get_local $0)
(i64.const 497826380083)
(i64.const 21967113313)
)
)
)
(set_local $1
(call $_ZN4NameC2Ey
(get_local $4)
(call $_ZN9ConstNameILy21967113313EE5valueEv)
)
)
(drop
(call $
_ZN2Db5storeI15CurrencyAccountEEl4NameS2_RKT_
(call $
store_i64
(i64.load
(get_local $0)
(i32.add
(i32.add
(get_local $2)
(i32.const 24)
)
(i32.const 8)
)
)
(i64.load
(get_local $1)
(i64.const 497826380083)
(i64.const 21967113313)
(i32.add
(get_local $2)
(i32.const 8)
)
(i32.const
32
)
(i32.const
8
)
)
)
(i32.store offset=4
(i32.const 0)
(i32.add
(get_local $4)
(i32.const 112)
)
)
)
(func $_Z14currentMessageI8TransferET_v (param $0 i32)
(drop
(call $readMessage
(call $_ZN8TransferC2Ev
(get_local $0)
)
(i32.const 24)
(get_local $2)
(i32.const 48)
)
)
)
(func $
_Z13requireNoticeIJyEEvyDpT_ (param $0 i64) (param $1 i64)
(local $
2
i32)
(func $
init
(local $
0
i32)
(i32.store offset=4
(i32.const 0)
(tee_local $
2
(tee_local $
0
(i32.sub
(i32.load offset=4
(i32.const 0)
...
...
@@ -346,552 +220,45 @@ const char* currency_wast = R"=====(
)
)
(i64.store offset=8
(get_local $2)
(get_local $0)
(i64.const 1000000000)
)
(i64.store
(get_local $2)
(get_local $1)
)
(call $requireNotice
(i64.load offset=8
(get_local $2)
)
)
(call $requireNotice
(i64.load
(get_local $2)
(drop
(call $store_i64
(i64.const 862690298531)
(i64.const 497826380083)
(i64.const 21967113313)
(i32.add
(get_local $0)
(i32.const 8)
)
(i32.const 8)
)
)
(i32.store offset=4
(i32.const 0)
(i32.add
(get_local $
2
)
(get_local $
0
)
(i32.const 16)
)
)
)
(func $_ZN15CurrencyAccountC2Ey (param $0 i32) (param $1 i64) (result i32)
(local $2 i32)
(i32.store offset=12
(tee_local $2
(i32.sub
(i32.load offset=4
(i32.const 0)
)
(i32.const 16)
)
)
(get_local $0)
)
(i64.store
(get_local $2)
(get_local $1)
)
(i64.store
(tee_local $2
(i32.load offset=12
(get_local $2)
)
)
(get_local $1)
)
(get_local $2)
)
(func $_ZN2Db3getI15CurrencyAccountEEb4NameS2_RT_ (param $0 i64) (param $1 i64) (param $2 i32) (result i32)
(local $3 i32)
(i32.store offset=4
(i32.const 0)
(tee_local $3
(i32.sub
(i32.load offset=4
(i32.const 0)
)
(i32.const 48)
)
)
)
(i64.store offset=40
(get_local $3)
(get_local $0)
)
(i64.store offset=32
(get_local $3)
(get_local $1)
)
(i32.store offset=28
(get_local $3)
(get_local $2)
)
(i32.store offset=20
(get_local $3)
(i32.load offset=44
(get_local $3)
)
)
(i32.store offset=16
(get_local $3)
(i32.load offset=40
(get_local $3)
)
)
(set_local $2
(call $_ZN4NameC2Ey
(i32.add
(get_local $3)
(i32.const 8)
(func $apply (param $0 i64) (param $1 i64)
(block $label$0
(br_if $label$0
(i64.ne
(get_local $0)
(i64.const 862690298531)
)
(call $currentCode)
)
)
(i64.store
(get_local $3)
(tee_local $1
(i64.load offset=32
(get_local $3)
)
)
)
(set_local $2
(call $_ZN2Db3getI15CurrencyAccountEEb4NameS2_S2_RT_
(i64.load offset=16
(get_local $3)
)
(i64.load
(get_local $2)
)
(get_local $1)
(i32.load offset=28
(get_local $3)
)
)
)
(i32.store offset=4
(i32.const 0)
(i32.add
(get_local $3)
(i32.const 48)
)
)
(get_local $2)
)
(func $_ZN4NameC2Ey (param $0 i32) (param $1 i64) (result i32)
(local $2 i32)
(i32.store offset=12
(tee_local $2
(i32.sub
(i32.load offset=4
(i32.const 0)
)
(i32.const 16)
)
)
(get_local $0)
)
(i64.store
(get_local $2)
(get_local $1)
)
(i64.store
(tee_local $2
(i32.load offset=12
(get_local $2)
)
)
(get_local $1)
)
(get_local $2)
)
(func $_ZN9ConstNameILy21967113313EE5valueEv (result i64)
(i64.const 21967113313)
)
(func $_ZN2Db6removeI15CurrencyAccountEEb4NameS2_ (param $0 i64) (param $1 i64) (result i32)
(local $2 i32)
(local $3 i32)
(i32.store offset=4
(i32.const 0)
(tee_local $3
(i32.sub
(i32.load offset=4
(i32.const 0)
)
(i32.const 32)
)
)
)
(i64.store offset=24
(get_local $3)
(get_local $0)
)
(i64.store offset=16
(get_local $3)
(get_local $1)
)
(set_local $1
(call $_ZNK4NamecvyEv
(i32.add
(get_local $3)
(i32.const 24)
)
)
)
(i64.store offset=8
(get_local $3)
(call $_ZN15CurrencyAccount7tableIdEv)
)
(set_local $2
(call $remove_i64
(get_local $1)
(call $_ZNK4NamecvyEv
(i32.add
(get_local $3)
(i32.const 8)
)
)
(call $_ZNK4NamecvyEv
(i32.add
(get_local $3)
(i32.const 16)
)
)
)
)
(i32.store offset=4
(i32.const 0)
(i32.add
(get_local $3)
(i32.const 32)
)
)
(i32.ne
(get_local $2)
(i32.const 0)
)
)
(func $_ZN2Db5storeI15CurrencyAccountEEl4NameS2_RKT_ (param $0 i64) (param $1 i64) (param $2 i32) (result i32)
(local $3 i32)
(i32.store offset=4
(i32.const 0)
(tee_local $3
(i32.sub
(i32.load offset=4
(i32.const 0)
)
(i32.const 32)
)
)
)
(i64.store offset=24
(get_local $3)
(get_local $0)
)
(i64.store offset=16
(get_local $3)
(get_local $1)
)
(i32.store offset=12
(get_local $3)
(get_local $2)
)
(set_local $1
(call $_ZNK4NamecvyEv
(i32.add
(get_local $3)
(i32.const 24)
)
)
)
(i64.store
(get_local $3)
(call $_ZN15CurrencyAccount7tableIdEv)
)
(set_local $2
(call $store_i64
(get_local $1)
(call $_ZNK4NamecvyEv
(get_local $3)
)
(call $_ZNK4NamecvyEv
(i32.add
(get_local $3)
(i32.const 16)
)
)
(i32.load offset=12
(get_local $3)
)
(i32.const 8)
)
)
(i32.store offset=4
(i32.const 0)
(i32.add
(get_local $3)
(i32.const 32)
)
)
(get_local $2)
)
(func $init
(local $0 i32)
(local $1 i32)
(local $2 i32)
(local $3 i32)
(i32.store offset=4
(i32.const 0)
(tee_local $3
(i32.sub
(i32.load offset=4
(i32.const 0)
)
(i32.const 32)
)
)
)
(set_local $0
(call $_ZN4NameC2Ey
(i32.add
(get_local $3)
(i32.const 24)
)
(call $_ZN9ConstNameILy862690298531EE5valueEv)
)
)
(set_local $1
(call $_ZN4NameC2Ey
(i32.add
(get_local $3)
(i32.const 16)
)
(call $_ZN9ConstNameILy21967113313EE5valueEv)
)
)
(set_local $2
(call $_ZN15CurrencyAccountC2Ey
(i32.add
(get_local $3)
(i32.const 8)
)
(i64.const 1000000000)
)
)
(drop
(call $_ZN2Db5storeI15CurrencyAccountEEl4NameS2_RKT_
(i64.load
(get_local $0)
)
(i64.load
(get_local $1)
)
(get_local $2)
)
)
(i32.store offset=4
(i32.const 0)
(i32.add
(get_local $3)
(i32.const 32)
)
)
)
(func $_ZN9ConstNameILy862690298531EE5valueEv (result i64)
(i64.const 862690298531)
)
(func $apply (param $0 i64) (param $1 i64)
(local $2 i32)
(i32.store offset=4
(i32.const 0)
(tee_local $2
(i32.sub
(i32.load offset=4
(i32.const 0)
)
(i32.const 16)
)
)
)
(i64.store offset=8
(get_local $2)
(get_local $0)
)
(i64.store
(get_local $2)
(get_local $1)
)
(block $label$0
(br_if $label$0
(i64.ne
(i64.load offset=8
(get_local $2)
)
(call $_ZN9ConstNameILy862690298531EE5valueEv)
)
)
(br_if $label$0
(i64.ne
(i64.load
(get_local $2)
)
(call $_ZN9ConstNameILy624065709652EE5valueEv)
(br_if $label$0
(i64.ne
(get_local $1)
(i64.const 624065709652)
)
)
(call $_Z23apply_currency_transferv)
)
(i32.store offset=4
(i32.const 0)
(i32.add
(get_local $2)
(i32.const 16)
)
)
)
(func $_ZN9ConstNameILy624065709652EE5valueEv (result i64)
(i64.const 624065709652)
)
(func $_ZN8TransferC2Ev (param $0 i32) (result i32)
(local $1 i32)
(set_local $1
(i32.load offset=4
(i32.const 0)
)
)
(i64.store offset=16
(get_local $0)
(i64.const 0)
)
(i32.store offset=12
(i32.sub
(get_local $1)
(i32.const 16)
)
(get_local $0)
)
(get_local $0)
)
(func $_ZN2Db3getI15CurrencyAccountEEb4NameS2_S2_RT_ (param $0 i64) (param $1 i64) (param $2 i64) (param $3 i32) (result i32)
(local $4 i32)
(i32.store offset=4
(i32.const 0)
(tee_local $4
(i32.sub
(i32.load offset=4
(i32.const 0)
)
(i32.const 48)
)
)
)
(i64.store offset=40
(get_local $4)
(get_local $0)
)
(i64.store offset=32
(get_local $4)
(get_local $1)
)
(i64.store offset=24
(get_local $4)
(get_local $2)
)
(i32.store offset=20
(get_local $4)
(get_local $3)
)
(set_local $2
(i64.load offset=32
(get_local $4)
)
)
(set_local $1
(i64.load offset=40
(get_local $4)
)
)
(i64.store offset=8
(get_local $4)
(tee_local $0
(call $_ZN15CurrencyAccount7tableIdEv)
)
)
(i32.store offset=16
(get_local $4)
(tee_local $3
(call $load_i64
(get_local $1)
(get_local $2)
(get_local $0)
(i64.load offset=24
(get_local $4)
)
(i32.load offset=20
(get_local $4)
)
(i32.const 8)
)
)
)
(i32.store offset=4
(i32.const 0)
(i32.add
(get_local $4)
(i32.const 48)
)
)
(i32.gt_s
(get_local $3)
(i32.const 0)
)
)
(func $_ZN15CurrencyAccount7tableIdEv (result i64)
(local $0 i64)
(local $1 i32)
(i32.store offset=4
(i32.const 0)
(tee_local $1
(i32.sub
(i32.load offset=4
(i32.const 0)
)
(i32.const 16)
)
)
)
(set_local $0
(i64.load
(call $_ZN4NameC2Ey
(i32.add
(get_local $1)
(i32.const 8)
)
(call $_ZN9ConstNameILy497826380083EE5valueEv)
)
)
)
(i32.store offset=4
(i32.const 0)
(i32.add
(get_local $1)
(i32.const 16)
)
)
(get_local $0)
)
(func $_ZN9ConstNameILy497826380083EE5valueEv (result i64)
(i64.const 497826380083)
)
(func $_ZNK4NamecvyEv (param $0 i32) (result i64)
(i32.store offset=12
(i32.sub
(i32.load offset=4
(i32.const 0)
)
(i32.const 16)
)
(get_local $0)
)
(i64.load
(get_local $0)
)
)
)
)====="
;
contracts/
currency
/eos.hpp
→
contracts/
eoslib
/eos.hpp
浏览文件 @
c5dba14c
...
...
@@ -4,9 +4,13 @@ typedef long long int64_t;
typedef
unsigned
long
long
uint64_t
;
typedef
unsigned
long
uint32_t
;
typedef
long
int32_t
;
typedef
unsigned
__int128
uint128_t
;
typedef
__int128
int128_t
;
typedef
unsigned
char
uint8_t
;
typedef
uint64_t
AccountName
;
typedef
uint64_t
TableName
;
typedef
uint32_t
Time
;
/**
* @param msg - a pointer where up to @ref len bytes of the current message will be coppied
...
...
@@ -42,6 +46,45 @@ int32_t store_i64( AccountName scope, TableName table, uint64_t key, const void*
int32_t
load_i64
(
AccountName
scope
,
AccountName
code
,
TableName
table
,
uint64_t
key
,
void
*
data
,
uint32_t
datalen
);
int32_t
remove_i64
(
AccountName
scope
,
TableName
table
,
uint64_t
key
);
/**
* These methods expect data to point to a record that is at least 2*sizeof(uint128_t) where the leading
* 32 bytes are the primary and secondary keys. These keys will be interpreted and sorted as unsigned
* 128 bit integers.
*
* @return the total number of bytes read or -1 for "not found" or "end".
*/
///@{
int32_t
front_primary_i128i128
(
AccountName
scope
,
AccountName
code
,
TableName
table
,
void
*
data
,
uint32_t
len
);
int32_t
back_primary_i128i128
(
AccountName
scope
,
AccountName
code
,
TableName
table
,
void
*
data
,
uint32_t
len
);
int32_t
next_primary_i128i128
(
AccountName
scope
,
AccountName
code
,
TableName
table
,
void
*
data
,
uint32_t
len
);
int32_t
previous_primary_i128i128
(
AccountName
scope
,
AccountName
code
,
TableName
table
,
void
*
data
,
uint32_t
len
);
int32_t
front_secondary_i128i128
(
AccountName
scope
,
AccountName
code
,
TableName
table
,
void
*
data
,
uint32_t
len
);
int32_t
back_secondary_i128i128
(
AccountName
scope
,
AccountName
code
,
TableName
table
,
void
*
data
,
uint32_t
len
);
int32_t
next_secondary_i128i128
(
AccountName
scope
,
AccountName
code
,
TableName
table
,
void
*
data
,
uint32_t
len
);
int32_t
previous_secondary_i128i128
(
AccountName
scope
,
AccountName
code
,
TableName
table
,
void
*
data
,
uint32_t
len
);
///@}
int32_t
upper_bound_primary_i128i128
(
AccountName
scope
,
AccountName
code
,
TableName
table
,
const
uint128_t
*
key
,
void
*
data
,
uint32_t
len
);
int32_t
lower_bound_primary_i128i128
(
AccountName
scope
,
AccountName
code
,
TableName
table
,
const
uint128_t
*
key
,
void
*
data
,
uint32_t
len
);
int32_t
upper_bound_secondary_i128i128
(
AccountName
scope
,
AccountName
code
,
TableName
table
,
const
uint128_t
*
key
,
void
*
data
,
uint32_t
len
);
int32_t
lower_bound_secondary_i128i128
(
AccountName
scope
,
AccountName
code
,
TableName
table
,
const
uint128_t
*
key
,
void
*
data
,
uint32_t
len
);
/// data must point to 2*sizeof(uint128) containing primary and secondary key
bool
remove_i128i128
(
AccountName
scope
,
TableName
table
,
void
*
data
);
/// data must point to at least 2*sizeof(uint128) containing primary and secondary key
bool
store_i128i128
(
AccountName
scope
,
TableName
table
,
void
*
data
,
uint32_t
len
);
int32_t
load_primary_i128i128
(
AccountName
scope
,
AccountName
code
,
TableName
table
,
const
void
*
primary
,
void
*
data
,
uint32_t
len
);
int32_t
load_secondary_i128i128
(
AccountName
scope
,
AccountName
code
,
TableName
table
,
const
void
*
secondary
,
void
*
data
,
uint32_t
len
);
void
print
(
const
char
*
cstr
);
void
printi
(
uint64_t
value
);
...
...
@@ -113,6 +156,11 @@ void disableContextCode( uint64_t AccountName );
}
/// extern C
template
<
typename
T
>
T
min
(
const
T
&
a
,
const
T
&
b
)
{
return
a
<
b
?
a
:
b
;
}
static
constexpr
char
char_to_symbol
(
char
c
)
{
if
(
c
>=
'a'
&&
c
<=
'z'
)
return
(
c
-
'a'
)
+
1
;
...
...
@@ -144,6 +192,7 @@ struct ConstName {
operator
uint64_t
()
const
{
return
I
;
}
};
#define NAME(X) (ConstName<string_to_name(X)>::value())
#define N(X) string_to_name(#X)
struct
Name
{
Name
(){}
...
...
@@ -158,10 +207,6 @@ struct Name {
struct
Db
{
template
<
typename
T
>
static
bool
test
(
Name
key
,
const
T
&
value
)
{
return
T
::
tableId
();
}
template
<
typename
T
>
static
bool
get
(
Name
key
,
T
&
value
){
...
...
@@ -199,6 +244,10 @@ struct Db
}
};
template
<
typename
T
>
struct
remove_reference
{
typedef
T
type
;
};
template
<
typename
T
>
struct
remove_reference
<
T
&>
{
typedef
T
type
;
};
template
<
typename
T
>
struct
remove_reference
<
const
T
&>
{
typedef
T
type
;
};
template
<
typename
T
>
T
currentMessage
()
{
T
value
;
...
...
@@ -220,3 +269,107 @@ struct Ratio {
static_assert
(
sizeof
(
Ratio
)
==
2
*
sizeof
(
uint64_t
),
"unexpected padding"
);
template
<
int
Primary
,
int
Secondary
>
struct
table_impl
{};
template
<
>
struct
table_impl
<
16
,
16
>
{
static
int32_t
front_primary
(
uint64_t
scope
,
uint64_t
code
,
uint64_t
table
,
void
*
data
,
uint32_t
len
)
{
return
front_primary_i128i128
(
scope
,
code
,
table
,
data
,
len
);
}
static
int32_t
back_primary
(
uint64_t
scope
,
uint64_t
code
,
uint64_t
table
,
void
*
data
,
uint32_t
len
)
{
return
back_primary_i128i128
(
scope
,
code
,
table
,
data
,
len
);
}
static
bool
remove
(
uint64_t
scope
,
uint64_t
table
,
void
*
data
)
{
return
remove_i128i128
(
scope
,
table
,
data
);
}
static
int32_t
load_primary
(
uint64_t
scope
,
uint64_t
code
,
uint64_t
table
,
const
void
*
primary
,
void
*
data
,
uint32_t
len
)
{
return
load_primary_i128i128
(
scope
,
code
,
table
,
primary
,
data
,
len
);
}
static
int32_t
front_secondary
(
AccountName
scope
,
AccountName
code
,
TableName
table
,
void
*
data
,
uint32_t
len
)
{
return
front_secondary_i128i128
(
scope
,
code
,
table
,
data
,
len
);
}
static
int32_t
back_secondary
(
AccountName
scope
,
AccountName
code
,
TableName
table
,
void
*
data
,
uint32_t
len
)
{
return
back_secondary_i128i128
(
scope
,
code
,
table
,
data
,
len
);
}
static
bool
store
(
AccountName
scope
,
TableName
table
,
void
*
data
,
uint32_t
len
)
{
return
store_i128i128
(
scope
,
table
,
data
,
len
);
}
};
template
<
uint64_t
scope
,
uint64_t
code
,
uint64_t
table
,
typename
Record
>
struct
Table
{
private:
typedef
typename
remove_reference
<
decltype
(
((
Record
*
)(
nullptr
))
->
primary
()
)
>::
type
Primary
;
typedef
typename
remove_reference
<
decltype
(
((
Record
*
)(
nullptr
))
->
secondary
()
)
>::
type
Secondary
;
typedef
table_impl
<
sizeof
(
Primary
),
sizeof
(
Secondary
)
>
impl
;
public:
struct
PrimaryIndex
{
static
bool
front
(
Record
&
r
)
{
return
impl
::
front_primary
(
scope
,
code
,
table
,
&
r
,
sizeof
(
Record
)
)
==
sizeof
(
Record
);
}
static
bool
back
(
Record
&
r
)
{
return
impl
::
back_primary
(
scope
,
code
,
table
,
&
r
,
sizeof
(
Record
)
)
==
sizeof
(
Record
);
}
static
bool
next
(
Record
&
r
)
{
return
impl
::
next_primary
(
scope
,
code
,
table
,
&
r
,
sizeof
(
Record
)
)
==
sizeof
(
Record
);
}
static
bool
previous
(
Record
&
r
)
{
return
impl
::
previous_primary
(
scope
,
code
,
table
,
&
r
,
sizeof
(
Record
)
)
==
sizeof
(
Record
);
}
static
bool
get
(
const
Primary
&
p
,
Record
&
r
)
{
return
impl
::
load_primary
(
scope
,
code
,
table
,
&
p
,
&
r
,
sizeof
(
Record
)
)
==
sizeof
(
Record
);
}
static
bool
lower_bound
(
const
Primary
&
p
,
Record
&
r
)
{
return
impl
::
lower_bound_primary
(
scope
,
code
,
table
,
&
p
&
r
,
sizeof
(
Record
)
)
==
sizeof
(
Record
);
}
static
bool
upper_bound
(
const
Primary
&
p
,
Record
&
r
)
{
return
impl
::
upper_bound_primary
(
scope
,
code
,
table
,
&
p
&
r
,
sizeof
(
Record
)
)
==
sizeof
(
Record
);
}
static
bool
remove
(
Record
&
r
)
{
impl
::
remove
(
scope
,
table
,
&
r
);
}
};
struct
SecondaryIndex
{
static
bool
front
(
Record
&
r
)
{
return
impl
::
front_secondary
(
scope
,
code
,
table
,
&
r
,
sizeof
(
Record
)
)
==
sizeof
(
Record
);
}
static
bool
back
(
Record
&
r
)
{
return
impl
::
back_secondary
(
scope
,
code
,
table
,
&
r
,
sizeof
(
Record
)
)
==
sizeof
(
Record
);
}
static
bool
next
(
Record
&
r
)
{
return
impl
::
next_secondary
(
scope
,
code
,
table
,
&
r
,
sizeof
(
Record
)
)
==
sizeof
(
Record
);
}
static
bool
previous
(
Record
&
r
)
{
return
impl
::
previous_secondary
(
scope
,
code
,
table
,
&
r
,
sizeof
(
Record
)
)
==
sizeof
(
Record
);
}
static
bool
get
(
const
Primary
&
p
,
Record
&
r
)
{
return
impl
::
load_secondary
(
scope
,
code
,
table
,
&
p
&
r
,
sizeof
(
Record
)
)
==
sizeof
(
Record
);
}
static
bool
lower_bound
(
const
Primary
&
p
,
Record
&
r
)
{
return
impl
::
lower_bound_secondary
(
scope
,
code
,
table
,
&
p
&
r
,
sizeof
(
Record
)
)
==
sizeof
(
Record
);
}
static
bool
upper_bound
(
const
Primary
&
p
,
Record
&
r
)
{
return
impl
::
upper_bound_secondary
(
scope
,
code
,
table
,
&
p
&
r
,
sizeof
(
Record
)
)
==
sizeof
(
Record
);
}
static
bool
remove
(
Record
&
r
)
{
impl
::
remove
(
scope
,
table
,
&
r
);
}
};
static
bool
store
(
Record
&
r
)
{
return
impl
::
store
(
scope
,
table
,
&
r
,
sizeof
(
r
)
);
}
static
bool
remove
(
Record
&
r
)
{
return
impl
::
remove
(
scope
,
table
,
&
r
);
}
};
#define TABLE(SCOPE, CODE, TABLE, TYPE) Table<N(SCOPE),N(CODE),N(TABLE),TYPE>
contracts/exchange/Makefile
0 → 100644
浏览文件 @
c5dba14c
exchange.wast
:
exchange.cpp Makefile ../eoslib/eos.hpp exchange.hpp
/usr/local/Cellar/llvm/4.0.0_1/bin/clang-4.0
-emit-llvm
-O3
--std
=
c++14
--target
=
wasm32
-c
exchange.cpp
-I
..
-fno-threadsafe-statics
-fno-rtti
-fno-exceptions
-o
.exchange.bc
-I
/usr/local/Cellar/llvm/4.0.0_1/include/c++/v1/
/Users/dlarimer/Downloads/llvm/build/bin/llc
-asm-verbose
=
false
.exchange.bc
/Users/dlarimer/eos/libraries/binaryen/bin/s2wasm
-s
1024 .exchange.s
>
exchange.wast
wc
-l
exchange.wast
echo
'#pragma once '
>
exchange.wast.hpp
echo
'const char* exchange_wast = R"=====('
>>
exchange.wast.hpp
cat
exchange.wast
>>
exchange.wast.hpp
echo
')=====";'
>>
exchange.wast.hpp
# /usr/local/Cellar/llvm/4.0.0_1/bin/clang-4.0 -emit-llvm -O3 --std=c++14 --target=wasm32 -nostdinc -c currency.cpp -I.. -fno-threadsafe-statics -fno-rtti -fno-exceptions -o .currency.bc
# /usr/local/Cellar/llvm/4.0.0_1/bin/clang-4.0 -emit-llvm --std=c++14 --target=wasm32 -nostdinc -c currency.cpp -I.. -fno-threadsafe-statics -fno-rtti -fno-exceptions -o .currency.bc
test.wast
:
test.cpp Makefile eos.hpp
/usr/local/Cellar/llvm/4.0.0_1/bin/clang-4.0
-emit-llvm
-O3
--std
=
c++14
--target
=
wasm32
-nostdinc
-c
test.cpp
-I
..
-fno-threadsafe-statics
-fno-rtti
-fno-exceptions
/Users/dlarimer/Downloads/llvm/build/bin/llc
-asm-verbose
=
false
test.bc
/Users/dlarimer/eos/libraries/binaryen/bin/s2wasm test.s
-s
1024
>
test.wast
cat
test.wast
contracts/exchange/exchange.cpp
浏览文件 @
c5dba14c
...
...
@@ -33,8 +33,40 @@
* creating, canceling, and filling orders do not require blocking either currency
* contract. Users can only deposit or withdraw to their own currency account.
*/
#include <c
ontracts
/currency.hpp> /// defines transfer struct
#include <c
urrency
/currency.hpp> /// defines transfer struct
typedef
uint128_t
Price
;
struct
OrderID
{
uint64_t
owner
=
0
;
uint64_t
id
=
0
;
operator
const
uint128_t
&
()
const
{
return
*
reinterpret_cast
<
const
uint128_t
*>
(
this
);
}
operator
uint128_t
&
(){
return
*
reinterpret_cast
<
uint128_t
*>
(
this
);
}
};
static_assert
(
sizeof
(
OrderID
)
==
sizeof
(
uint128_t
),
"unexpected packing"
);
struct
Order
{
OrderID
&
primary
()
{
return
id
;
}
Price
&
secondary
(){
return
price
;
}
OrderID
id
;
Price
price
;
uint64_t
quantity
;
Time
expiration
;
};
using
Bids
=
TABLE
(
exchange
,
exchange
,
bids
,
Order
);
using
Asks
=
TABLE
(
exchange
,
exchange
,
asks
,
Order
);
typedef
Asks
::
SecondaryIndex
AsksByPrice
;
typedef
Bids
::
SecondaryIndex
BidsByPrice
;
typedef
Asks
::
PrimaryIndex
AsksById
;
typedef
Bids
::
PrimaryIndex
BidsById
;
struct
Account
{
uint64_t
a
=
0
;
...
...
@@ -42,11 +74,8 @@ struct Account {
int
open_orders
=
0
;
bool
isEmpty
()
const
{
return
!
(
a
|
b
|
open_orders
);
}
/**
* Balance records for all exchange users are stored here
* exchange/exchange/balance/username -> Balance
*/
static
Name
tableId
()
{
return
Name
(
"balance"
);
}
static
Name
tableId
()
{
return
NAME
(
"account"
);
}
};
...
...
@@ -58,21 +87,21 @@ struct Account {
void
apply_currencya_transfer
()
{
const
auto
&
transfer
=
currentMessage
<
Transfer
>
();
if
(
transfer
.
to
==
"exchange"
)
{
static
Balance
to_balance
;
if
(
transfer
.
to
==
N
(
exchange
)
)
{
Account
to_balance
;
Db
::
get
(
transfer
.
from
,
to_balance
);
to_balance
.
a
+=
transfer
.
amount
;
Db
::
store
(
transfer
.
from
,
to_balance
);
}
else
if
(
transfer
.
from
==
"exchange"
)
{
}
else
if
(
transfer
.
from
==
N
(
exchange
)
)
{
requireAuth
(
transfer
.
to
);
/// require the reciever of funds (account owner) to authorize this transfer
static
Balance
to_balance
;
auto
balance
=
Db
::
get
(
transfer
.
to
,
to_balance
);
assert
(
balance
.
a
>=
transfer
.
amount
,
"insufficient funds to withdraw"
);
balance
.
a
-=
transfer
.
amount
;
Account
to_balance
;
Db
::
get
(
transfer
.
to
,
to_balance
);
assert
(
to_
balance
.
a
>=
transfer
.
amount
,
"insufficient funds to withdraw"
);
to_
balance
.
a
-=
transfer
.
amount
;
if
(
balance
.
isEmpty
()
)
Db
::
remove
<
Balance
>
(
transfer
.
to
);
if
(
to_
balance
.
isEmpty
()
)
Db
::
remove
<
Account
>
(
transfer
.
to
);
else
Db
::
store
(
transfer
.
to
,
to_balance
);
}
else
{
...
...
@@ -80,28 +109,24 @@ void apply_currencya_transfer() {
}
}
/**
* This method is called after the "transfer" action of code
* "currencya" is called and "exchange" is listed in the notifiers.
*/
void
apply_currencyb_transfer
()
{
const
auto
&
transfer
=
currentMessage
<
Transfer
>
();
if
(
transfer
.
to
==
"exchange"
)
{
static
Balance
to_balance
;
if
(
transfer
.
to
==
N
(
exchange
)
)
{
Account
to_balance
;
Db
::
get
(
transfer
.
from
,
to_balance
);
to_balance
.
b
+=
transfer
.
amount
;
Db
::
store
(
transfer
.
from
,
to_balance
);
}
else
if
(
transfer
.
from
==
"exchange"
)
{
}
else
if
(
transfer
.
from
==
N
(
exchange
)
)
{
requireAuth
(
transfer
.
to
);
/// require the reciever of funds (account owner) to authorize this transfer
static
Balance
to_balance
;
auto
balance
=
Db
::
get
(
transfer
.
to
,
to_balance
);
assert
(
balance
.
b
>=
transfer
.
amount
,
"insufficient funds to withdraw"
);
balance
.
b
-=
transfer
.
amount
;
Account
to_balance
;
Db
::
get
(
transfer
.
to
,
to_balance
);
assert
(
to_
balance
.
b
>=
transfer
.
amount
,
"insufficient funds to withdraw"
);
to_
balance
.
b
-=
transfer
.
amount
;
if
(
balance
.
isEmpty
()
)
Db
::
remove
<
Balance
>
(
transfer
.
to
);
if
(
to_
balance
.
isEmpty
()
)
Db
::
remove
<
Account
>
(
transfer
.
to
);
else
Db
::
store
(
transfer
.
to
,
to_balance
);
}
else
{
...
...
@@ -109,13 +134,181 @@ void apply_currencyb_transfer() {
}
}
struct
Buy
{
AccountName
buyer
;
Price
price
;
uint64_t
quantity
=
0
;
uint32_t
id
=
0
;
Time
expiration
;
uint8_t
fill_or_kill
=
false
;
};
struct
Sell
{
AccountName
seller
;
Price
price
;
uint64_t
quantity
=
0
;
uint32_t
id
=
0
;
Time
expiration
;
uint8_t
fill_or_kill
=
false
;
};
void
fill
(
Order
&
bid
,
Order
&
ask
,
Account
&
buyer
,
Account
&
seller
,
uint64_t
usd
,
uint64_t
token
)
{
bid
.
quantity
-=
usd
;
seller
.
a
+=
usd
;
ask
.
quantity
-=
token
;
buyer
.
b
+=
token
;
}
/**
*
*
*/
void
apply_exchange_buy
()
{
auto
buy
=
currentMessage
<
Buy
>
();
assert
(
buy
.
expiration
>
now
(),
"order expired"
);
Account
buyer_account
;
Db
::
get
(
buy
.
buyer
,
buyer_account
);
assert
(
buyer_account
.
a
>=
buy
.
quantity
,
"insufficient funds"
);
assert
(
buy
.
quantity
>
0
,
"invalid quantity"
);
buyer_account
.
a
-=
buy
.
quantity
;
Order
buyer_bid
;
assert
(
BidsById
::
get
(
OrderID
{
buy
.
buyer
,
buy
.
id
},
buyer_bid
),
"order with this id already exists"
);
buyer_bid
.
price
=
buy
.
price
;
buyer_bid
.
id
.
owner
=
buy
.
buyer
;
buyer_bid
.
id
.
id
=
buy
.
id
;
buyer_bid
.
quantity
=
buy
.
quantity
;
buyer_bid
.
expiration
=
buy
.
expiration
;
Order
lowest_ask
;
if
(
!
AsksByPrice
::
front
(
lowest_ask
)
)
{
assert
(
!
buy
.
fill_or_kill
,
"order not completely filled"
);
Bids
::
store
(
buyer_bid
);
Db
::
store
(
buy
.
buyer
,
buyer_account
);
return
;
}
Account
seller_account
;
Db
::
get
(
lowest_ask
.
id
.
owner
,
seller_account
);
while
(
lowest_ask
.
price
<=
buyer_bid
.
price
)
{
auto
ask_usd
=
lowest_ask
.
price
*
lowest_ask
.
quantity
;
auto
fill_amount_usd
=
min
<
uint64_t
>
(
ask_usd
,
buyer_bid
.
quantity
);
uint64_t
fill_amount_token
=
0
;
lowest_ask
.
quantity
-=
fill_amount_token
;
buy
.
quantity
-=
fill_amount_usd
;
if
(
fill_amount_usd
==
ask_usd
)
{
/// complete fill of ask
fill_amount_token
=
lowest_ask
.
quantity
;
}
else
{
/// complete fill of buy
fill_amount_token
=
fill_amount_usd
/
lowest_ask
.
price
;
}
/// either fill_amount_token == seller.quantity or fill_amount_usd == buy.quantity
fill
(
buyer_bid
,
lowest_ask
,
buyer_account
,
seller_account
,
fill_amount_usd
,
fill_amount_token
);
if
(
lowest_ask
.
quantity
==
0
)
{
Db
::
store
(
lowest_ask
.
id
.
owner
,
seller_account
);
Asks
::
remove
(
lowest_ask
);
if
(
!
AsksByPrice
::
front
(
lowest_ask
)
)
{
break
;
}
Db
::
get
(
lowest_ask
.
id
.
owner
,
seller_account
);
}
else
{
break
;
// buyer's bid should be filled
}
}
Db
::
store
(
buy
.
buyer
,
buyer_account
);
if
(
buyer_bid
.
quantity
>
0
)
{
assert
(
!
buy
.
fill_or_kill
,
"order not completely filled"
);
Bids
::
store
(
buyer_bid
);
}
}
void
apply_exchange_sell
()
{
auto
sell
=
currentMessage
<
Sell
>
();
assert
(
sell
.
expiration
>
now
(),
"order expired"
);
Account
seller_account
;
Db
::
get
(
sell
.
seller
,
seller_account
);
assert
(
seller_account
.
b
>=
sell
.
quantity
,
"insufficient funds"
);
assert
(
sell
.
quantity
>
0
,
"invalid quantity"
);
seller_account
.
b
-=
sell
.
quantity
;
Order
seller_ask
;
assert
(
AsksById
::
get
(
OrderID
{
sell
.
seller
,
sell
.
id
},
seller_ask
),
"order with this id already exists"
);
seller_ask
.
price
=
sell
.
price
;
seller_ask
.
id
.
owner
=
sell
.
seller
;
seller_ask
.
id
.
id
=
sell
.
id
;
seller_ask
.
quantity
=
sell
.
quantity
;
seller_ask
.
expiration
=
sell
.
expiration
;
Order
highest_bid
;
if
(
!
BidsByPrice
::
back
(
highest_bid
)
)
{
assert
(
!
sell
.
fill_or_kill
,
"order not completely filled"
);
Bids
::
store
(
seller_ask
);
Db
::
store
(
sell
.
seller
,
seller_account
);
return
;
}
Account
buyer_account
;
Db
::
get
(
highest_bid
.
id
.
owner
,
buyer_account
);
while
(
highest_bid
.
price
>=
seller_ask
.
price
)
{
auto
ask_usd
=
seller_ask
.
quantity
;
auto
bid_usd
=
seller_ask
.
price
*
seller_ask
.
quantity
;
auto
fill_amount_usd
=
min
<
uint64_t
>
(
ask_usd
,
bid_usd
);
uint64_t
fill_amount_token
=
0
;
seller_ask
.
quantity
-=
fill_amount_token
;
highest_bid
.
quantity
-=
fill_amount_usd
;
if
(
fill_amount_usd
==
ask_usd
)
{
/// complete fill of ask
fill_amount_token
=
seller_ask
.
quantity
;
}
else
{
/// complete fill of buy
fill_amount_token
=
fill_amount_usd
/
seller_ask
.
price
;
}
/// either fill_amount_token == seller.quantity or fill_amount_usd == buy.quantity
fill
(
highest_bid
,
seller_ask
,
buyer_account
,
seller_account
,
fill_amount_usd
,
fill_amount_token
);
if
(
highest_bid
.
quantity
==
0
)
{
Db
::
store
(
highest_bid
.
id
.
owner
,
buyer_account
);
Asks
::
remove
(
highest_bid
);
if
(
!
BidsByPrice
::
back
(
highest_bid
)
)
{
break
;
}
Db
::
get
(
highest_bid
.
id
.
owner
,
buyer_account
);
}
else
{
break
;
// buyer's bid should be filled
}
}
Db
::
store
(
sell
.
seller
,
seller_account
);
if
(
seller_ask
.
quantity
>
0
)
{
assert
(
!
sell
.
fill_or_kill
,
"order not completely filled"
);
Asks
::
store
(
seller_ask
);
}
}
ex
port
"C"
{
ex
tern
"C"
{
void
init
()
{
/*
setAuthority( "currencya", "transfer", "anyone" );
setAuthority( "currencyb", "transfer", "anyone" );
registerHandler( "apply", "currencya", "transfer" );
registerHandler( "apply", "currencyb", "transfer" );
*/
}
// void validate( uint64_t code, uint64_t action ) { }
...
...
@@ -124,10 +317,10 @@ export "C" {
* The apply method implements the dispatch of events to this contract
*/
void
apply
(
uint64_t
code
,
uint64_t
action
)
{
if
(
code
==
"currencya"
)
{
if
(
action
==
"transfer"
)
apply_currencya_transfer
();
}
else
if
(
code
==
"currencyb"
)
{
if
(
action
==
"transfer"
)
apply_currencyb_transfer
();
if
(
code
==
N
(
currencya
)
)
{
if
(
action
==
N
(
transfer
)
)
apply_currencya_transfer
();
}
else
if
(
code
==
N
(
currencyb
)
)
{
if
(
action
==
N
(
transfer
)
)
apply_currencyb_transfer
();
}
else
{
}
}
...
...
libraries/chain/include/eos/chain/key_value_object.hpp
浏览文件 @
c5dba14c
...
...
@@ -57,8 +57,50 @@ namespace eos { namespace chain {
>
>
;
struct
key128x128_value_object
:
public
chainbase
::
object
<
key128x128_value_object_type
,
key128x128_value_object
>
{
OBJECT_CTOR
(
key128x128_value_object
,
(
value
))
id_type
id
;
AccountName
scope
;
AccountName
code
;
AccountName
table
;
uint128_t
primary_key
;
uint128_t
secondary_key
;
shared_string
value
;
};
struct
by_scope_primary
;
struct
by_scope_secondary
;
using
key128x128_value_index
=
chainbase
::
shared_multi_index_container
<
key128x128_value_object
,
indexed_by
<
ordered_unique
<
tag
<
by_id
>
,
member
<
key128x128_value_object
,
key128x128_value_object
::
id_type
,
&
key128x128_value_object
::
id
>>
,
ordered_unique
<
tag
<
by_scope_primary
>
,
composite_key
<
key128x128_value_object
,
member
<
key128x128_value_object
,
AccountName
,
&
key128x128_value_object
::
scope
>
,
member
<
key128x128_value_object
,
AccountName
,
&
key128x128_value_object
::
code
>
,
member
<
key128x128_value_object
,
AccountName
,
&
key128x128_value_object
::
table
>
,
member
<
key128x128_value_object
,
uint128_t
,
&
key128x128_value_object
::
primary_key
>
,
member
<
key128x128_value_object
,
uint128_t
,
&
key128x128_value_object
::
secondary_key
>
>
,
composite_key_compare
<
std
::
less
<
AccountName
>
,
std
::
less
<
AccountName
>
,
std
::
less
<
AccountName
>
,
std
::
less
<
uint128_t
>
,
std
::
less
<
uint128_t
>
>
>
,
ordered_unique
<
tag
<
by_scope_secondary
>
,
composite_key
<
key128x128_value_object
,
member
<
key128x128_value_object
,
AccountName
,
&
key128x128_value_object
::
scope
>
,
member
<
key128x128_value_object
,
AccountName
,
&
key128x128_value_object
::
code
>
,
member
<
key128x128_value_object
,
AccountName
,
&
key128x128_value_object
::
table
>
,
member
<
key128x128_value_object
,
uint128_t
,
&
key128x128_value_object
::
secondary_key
>
,
member
<
key128x128_value_object
,
uint128_t
,
&
key128x128_value_object
::
primary_key
>
>
,
composite_key_compare
<
std
::
less
<
AccountName
>
,
std
::
less
<
AccountName
>
,
std
::
less
<
AccountName
>
,
std
::
less
<
uint128_t
>
,
std
::
less
<
uint128_t
>
>
>
>
>
;
}
}
// eos::chain
CHAINBASE_SET_INDEX_TYPE
(
eos
::
chain
::
key_value_object
,
eos
::
chain
::
key_value_index
)
CHAINBASE_SET_INDEX_TYPE
(
eos
::
chain
::
key128x128_value_object
,
eos
::
chain
::
key128x128_value_index
)
FC_REFLECT
(
eos
::
chain
::
key_value_object
,
(
id
)(
scope
)(
code
)(
table
)(
key
)(
value
)
)
libraries/chain/include/eos/chain/message_handling_contexts.hpp
浏览文件 @
c5dba14c
...
...
@@ -38,6 +38,18 @@ public:
int32_t
load_i64
(
Name
scope
,
Name
code
,
Name
table
,
Name
Key
,
char
*
data
,
uint32_t
maxlen
);
int32_t
front_primary_i128i128
(
Name
scope
,
Name
code
,
Name
table
,
uint128_t
*
primary
,
uint128_t
*
secondary
,
char
*
data
,
uint32_t
maxlen
);
int32_t
back_primary_i128i128
(
Name
scope
,
Name
code
,
Name
table
,
uint128_t
*
primary
,
uint128_t
*
secondary
,
char
*
data
,
uint32_t
maxlen
);
int32_t
load_primary_i128i128
(
Name
scope
,
Name
code
,
Name
table
,
uint128_t
*
primary
,
uint128_t
*
secondary
,
char
*
data
,
uint32_t
maxlen
);
int32_t
lowerbound_primary_i128i128
(
Name
scope
,
Name
code
,
Name
table
,
uint128_t
*
primary
,
uint128_t
*
secondary
,
char
*
data
,
uint32_t
maxlen
);
int32_t
lowerbound_secondary_i128i128
(
Name
scope
,
Name
code
,
Name
table
,
uint128_t
*
primary
,
uint128_t
*
secondary
,
char
*
data
,
uint32_t
maxlen
);
///< Parallel to msg.authorization; tracks which permissions have been used while processing the message
vector
<
bool
>
used_authorizations
;
};
...
...
libraries/chain/include/eos/chain/types.hpp
浏览文件 @
c5dba14c
...
...
@@ -133,6 +133,7 @@ namespace eos { namespace chain {
using
eos
::
types
::
Int64
;
using
eos
::
types
::
Int128
;
using
eos
::
types
::
Int256
;
using
eos
::
types
::
uint128_t
;
using
ProducerRound
=
std
::
array
<
AccountName
,
config
::
BlocksPerRound
>
;
using
RoundChanges
=
std
::
map
<
AccountName
,
AccountName
>
;
...
...
@@ -162,6 +163,7 @@ namespace eos { namespace chain {
permission_object_type
,
action_code_object_type
,
key_value_object_type
,
key128x128_value_object_type
,
action_permission_object_type
,
global_property_object_type
,
dynamic_global_property_object_type
,
...
...
@@ -206,6 +208,7 @@ FC_REFLECT_ENUM(eos::chain::object_type,
(
permission_object_type
)
(
action_code_object_type
)
(
key_value_object_type
)
(
key128x128_value_object_type
)
(
action_permission_object_type
)
(
global_property_object_type
)
(
dynamic_global_property_object_type
)
...
...
libraries/chain/message_handling_contexts.cpp
浏览文件 @
c5dba14c
...
...
@@ -58,6 +58,80 @@ int32_t message_validate_context::load_i64( Name scope, Name code, Name table, N
return
copylen
;
}
int32_t
message_validate_context
::
load_primary_i128i128
(
Name
scope
,
Name
code
,
Name
table
,
uint128_t
*
primary
,
uint128_t
*
secondary
,
char
*
value
,
uint32_t
valuelen
)
{
require_scope
(
scope
);
const
auto
&
idx
=
db
.
get_index
<
key128x128_value_index
,
by_scope_primary
>
();
auto
itr
=
idx
.
lower_bound
(
boost
::
make_tuple
(
AccountName
(
scope
),
AccountName
(
code
),
AccountName
(
table
),
*
primary
,
uint128_t
(
0
)
)
);
if
(
itr
==
idx
.
end
()
||
itr
->
scope
!=
scope
||
itr
->
code
!=
code
||
itr
->
table
!=
table
||
itr
->
primary_key
!=
*
primary
)
return
-
1
;
*
secondary
=
itr
->
secondary_key
;
auto
copylen
=
std
::
min
<
size_t
>
(
itr
->
value
.
size
(),
valuelen
);
if
(
copylen
)
{
itr
->
value
.
copy
(
value
,
copylen
);
}
return
copylen
;
}
int32_t
message_validate_context
::
lowerbound_primary_i128i128
(
Name
scope
,
Name
code
,
Name
table
,
uint128_t
*
primary
,
uint128_t
*
secondary
,
char
*
value
,
uint32_t
valuelen
)
{
require_scope
(
scope
);
const
auto
&
idx
=
db
.
get_index
<
key128x128_value_index
,
by_scope_primary
>
();
auto
itr
=
idx
.
lower_bound
(
boost
::
make_tuple
(
AccountName
(
scope
),
AccountName
(
code
),
AccountName
(
table
),
*
primary
,
uint128_t
(
0
)
)
);
if
(
itr
==
idx
.
end
()
||
itr
->
scope
!=
scope
||
itr
->
code
!=
code
||
itr
->
table
!=
table
)
return
-
1
;
*
primary
=
itr
->
primary_key
;
*
secondary
=
itr
->
secondary_key
;
auto
copylen
=
std
::
min
<
size_t
>
(
itr
->
value
.
size
(),
valuelen
);
if
(
copylen
)
{
itr
->
value
.
copy
(
value
,
copylen
);
}
return
copylen
;
}
int32_t
message_validate_context
::
lowerbound_secondary_i128i128
(
Name
scope
,
Name
code
,
Name
table
,
uint128_t
*
primary
,
uint128_t
*
secondary
,
char
*
value
,
uint32_t
valuelen
)
{
require_scope
(
scope
);
const
auto
&
idx
=
db
.
get_index
<
key128x128_value_index
,
by_scope_secondary
>
();
auto
itr
=
idx
.
lower_bound
(
boost
::
make_tuple
(
AccountName
(
scope
),
AccountName
(
code
),
AccountName
(
table
),
uint128_t
(
0
),
*
secondary
)
);
if
(
itr
==
idx
.
end
()
||
itr
->
scope
!=
scope
||
itr
->
code
!=
code
||
itr
->
table
!=
table
)
return
-
1
;
*
primary
=
itr
->
primary_key
;
*
secondary
=
itr
->
secondary_key
;
auto
copylen
=
std
::
min
<
size_t
>
(
itr
->
value
.
size
(),
valuelen
);
if
(
copylen
)
{
itr
->
value
.
copy
(
value
,
copylen
);
}
return
copylen
;
}
int32_t
apply_context
::
remove_i64
(
Name
scope
,
Name
table
,
Name
key
)
{
require_scope
(
scope
);
...
...
libraries/types/include/eos/types/native.hpp
浏览文件 @
c5dba14c
...
...
@@ -54,6 +54,7 @@ namespace eos { namespace types {
using
Int64
=
int64_t
;
//Int<64>;
using
Int128
=
boost
::
multiprecision
::
int128_t
;
using
Int256
=
boost
::
multiprecision
::
int256_t
;
using
uint128_t
=
unsigned
__int128
;
/// native clang/gcc 128 intrinisic
struct
Name
{
uint64_t
value
=
0
;
...
...
tests/tests/block_tests.cpp
浏览文件 @
c5dba14c
...
...
@@ -137,6 +137,91 @@ using namespace chain;
BOOST_AUTO_TEST_SUITE
(
block_tests
)
/**
* The purpose of this test is to demonstrate that it is possible
* to schedule 3M transactions into cycles where each cycle contains
* a set of independent transactions.
*
* This simple single threaded algorithm sorts 3M transactions each of which
* requires scope of 2 accounts chosen with a normal probability distribution
* amoung a set of 2 million accounts.
*
* This algorithm executes in less than 0.5 seconds on a 4Ghz Core i7 and could
* potentially take just .05 seconds with 10+ CPU cores. Future improvements might
* use a more robust bloomfilter to identify collisions.
*/
///@{
struct
Location
{
uint32_t
thread
=
-
1
;
uint32_t
cycle
=
-
1
;
Location
&
operator
=
(
const
Location
&
l
)
{
thread
=
l
.
thread
;
cycle
=
l
.
cycle
;
return
*
this
;
}
};
struct
ExTransaction
:
public
Transaction
{
Location
location
;
};
BOOST_AUTO_TEST_CASE
(
schedule_test
)
{
vector
<
ExTransaction
*>
transactions
(
3
*
1000
*
1000
);
auto
rand_scope
=
[]()
{
return
rand
()
%
1000000
+
rand
()
%
1000000
;
};
for
(
auto
&
t
:
transactions
)
{
t
=
new
ExTransaction
();
t
->
scope
=
sort_names
({
rand_scope
(),
rand_scope
()
});
}
int
cycle
=
0
;
std
::
vector
<
int
>
thread_count
(
1024
);
vector
<
ExTransaction
*>
postponed
;
postponed
.
reserve
(
transactions
.
size
());
auto
current
=
transactions
;
vector
<
bool
>
used
(
1024
*
1024
);
auto
start
=
fc
::
time_point
::
now
();
bool
scheduled
=
true
;
while
(
scheduled
)
{
scheduled
=
false
;
for
(
auto
t
:
current
)
{
bool
u
=
false
;
for
(
const
auto
&
s
:
t
->
scope
)
{
if
(
used
[
s
.
value
%
used
.
size
()]
)
{
u
=
true
;
postponed
.
push_back
(
t
);
break
;
}
}
if
(
!
u
)
{
for
(
const
auto
&
s
:
t
->
scope
)
{
used
[
s
.
value
%
used
.
size
()]
=
true
;
}
t
->
location
.
cycle
=
cycle
;
t
->
location
.
thread
=
thread_count
[
cycle
]
++
;
scheduled
=
true
;
}
}
current
.
resize
(
0
);
used
.
resize
(
0
);
used
.
resize
(
1024
*
1024
);
std
::
swap
(
current
,
postponed
);
++
cycle
;
}
auto
end
=
fc
::
time_point
::
now
();
thread_count
.
resize
(
cycle
+
1
);
// idump((cycle));
// idump((thread_count));
auto
sort_time
=
end
-
start
;
edump
((
sort_time
.
count
()
/
1000000.0
));
}
///@} end of schedule test
BOOST_AUTO_TEST_CASE
(
name_test
)
{
using
eos
::
types
::
Name
;
Name
temp
;
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录