/
app.go
163 lines (145 loc) · 5.14 KB
/
app.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
/*
Package app links together all the various components
to construct the bnsd app.
*/
package app
import (
"context"
"fmt"
"path/filepath"
"strings"
"github.com/iov-one/weave"
"github.com/iov-one/weave/app"
"github.com/iov-one/weave/cmd/bnsd/x/nft/username"
"github.com/iov-one/weave/coin"
"github.com/iov-one/weave/commands/server"
"github.com/iov-one/weave/orm"
"github.com/iov-one/weave/store/iavl"
"github.com/iov-one/weave/x"
"github.com/iov-one/weave/x/cash"
"github.com/iov-one/weave/x/currency"
"github.com/iov-one/weave/x/distribution"
"github.com/iov-one/weave/x/escrow"
"github.com/iov-one/weave/x/hashlock"
"github.com/iov-one/weave/x/msgfee"
"github.com/iov-one/weave/x/multisig"
"github.com/iov-one/weave/x/nft"
"github.com/iov-one/weave/x/nft/base"
"github.com/iov-one/weave/x/sigs"
"github.com/iov-one/weave/x/utils"
"github.com/iov-one/weave/x/validators"
)
// Authenticator returns the typical authentication,
// just using public key signatures
func Authenticator() x.Authenticator {
return x.ChainAuth(sigs.Authenticate{}, hashlock.Authenticate{}, multisig.Authenticate{})
}
// Chain returns a chain of decorators, to handle authentication,
// fees, logging, and recovery
func Chain(authFn x.Authenticator, minFee coin.Coin) app.Decorators {
// ctrl can be initialized with any implementation, but must be used
// consistently everywhere.
var ctrl cash.Controller = cash.NewController(cash.NewBucket())
return app.ChainDecorators(
utils.NewLogging(),
utils.NewRecovery(),
utils.NewKeyTagger(),
// on CheckTx, bad tx don't affect state
utils.NewSavepoint().OnCheck(),
sigs.NewDecorator(),
multisig.NewDecorator(authFn),
cash.NewDynamicFeeDecorator(authFn, ctrl),
msgfee.NewFeeDecorator(),
msgfee.NewAntispamFeeDecorator(minFee),
// cannot pay for fee with hashlock...
hashlock.NewDecorator(),
// batch commented out temporarily to minimize release features
// make sure we execute all the transactions in batch before the save point
//batch.NewDecorator(),
)
}
// Router returns a default router, only dispatching to the
// cash.SendMsg
func Router(authFn x.Authenticator, issuer weave.Address, nftBuckets map[string]orm.Bucket) app.Router {
r := app.NewRouter()
// ctrl can be initialized with any implementation, but must be used
// consistently everywhere.
var ctrl cash.Controller = cash.NewController(cash.NewBucket())
cash.RegisterRoutes(r, authFn, ctrl)
escrow.RegisterRoutes(r, authFn, ctrl)
multisig.RegisterRoutes(r, authFn)
//TODO: Possibly revisit passing the bucket later to have more control over types?
// or implement a check
currency.RegisterRoutes(r, authFn, issuer)
username.RegisterRoutes(r, authFn, issuer)
validators.RegisterRoutes(r, authFn, validators.NewController())
distribution.RegisterRoutes(r, authFn, ctrl)
base.RegisterRoutes(r, authFn, issuer, nftBuckets)
sigs.RegisterRoutes(r, authFn)
return r
}
// QueryRouter returns a default query router,
// allowing access to "/wallets", "/auth", "/", "/escrows", "/nft/usernames",
// "/nft/blockchains", "/nft/tickers", "/validators"
func QueryRouter(minFee coin.Coin) weave.QueryRouter {
r := weave.NewQueryRouter()
antiSpamQuery := msgfee.NewAntiSpamQuery(minFee)
r.RegisterAll(
escrow.RegisterQuery,
cash.RegisterQuery,
sigs.RegisterQuery,
multisig.RegisterQuery,
username.RegisterQuery,
validators.RegisterQuery,
orm.RegisterQuery,
currency.RegisterQuery,
distribution.RegisterQuery,
antiSpamQuery.RegisterQuery,
)
return r
}
// Register nft types and actions for shared action handling via base handler
func RegisterNft() {
// Default nft actions.
nft.RegisterAction(nft.DefaultActions...)
}
// Stack wires up a standard router with a standard decorator
// chain. This can be passed into BaseApp.
func Stack(issuer weave.Address, nftBuckets map[string]orm.Bucket, minFee coin.Coin) weave.Handler {
authFn := Authenticator()
return Chain(authFn, minFee).WithHandler(Router(authFn, issuer, nftBuckets))
}
// Application constructs a basic ABCI application with
// the given arguments. If you are not sure what to use
// for the Handler, just use Stack().
func Application(name string, h weave.Handler,
tx weave.TxDecoder, dbPath string, options *server.Options) (app.BaseApp, error) {
ctx := context.Background()
kv, err := CommitKVStore(dbPath)
if err != nil {
return app.BaseApp{}, err
}
RegisterNft()
store := app.NewStoreApp(name, kv, QueryRouter(options.MinFee), ctx)
base := app.NewBaseApp(store, tx, h, nil, options.Debug)
return base, nil
}
// CommitKVStore returns an initialized KVStore that persists
// the data to the named path.
func CommitKVStore(dbPath string) (weave.CommitKVStore, error) {
// memory backed case, just for testing
if dbPath == "" {
return iavl.MockCommitStore(), nil
}
// Expand the path fully
path, err := filepath.Abs(dbPath)
if err != nil {
return nil, fmt.Errorf("Invalid Database Name: %s", path)
}
// Some external calls accidently add a ".db", which is now removed
path = strings.TrimSuffix(path, filepath.Ext(path))
// Split the database name into it's components (dir, name)
dir := filepath.Dir(path)
name := filepath.Base(path)
return iavl.NewCommitStore(dir, name), nil
}