Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
G
Geth-Modification
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
张蕾
Geth-Modification
Commits
06d40d37
Unverified
Commit
06d40d37
authored
Sep 21, 2018
by
Péter Szilágyi
Committed by
GitHub
Sep 21, 2018
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #17732 from karalabe/faucet-caching
cmd/faucet: cache internal state, avoid sync-trashing les
parents
ee92bc53
c528e3e3
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
67 additions
and
45 deletions
+67
-45
faucet.go
cmd/faucet/faucet.go
+67
-45
No files found.
cmd/faucet/faucet.go
View file @
06d40d37
...
@@ -199,6 +199,8 @@ type faucet struct {
...
@@ -199,6 +199,8 @@ type faucet struct {
keystore
*
keystore
.
KeyStore
// Keystore containing the single signer
keystore
*
keystore
.
KeyStore
// Keystore containing the single signer
account
accounts
.
Account
// Account funding user faucet requests
account
accounts
.
Account
// Account funding user faucet requests
head
*
types
.
Header
// Current head header of the faucet
balance
*
big
.
Int
// Current balance of the faucet
nonce
uint64
// Current pending nonce of the faucet
nonce
uint64
// Current pending nonce of the faucet
price
*
big
.
Int
// Current gas price to issue funds with
price
*
big
.
Int
// Current gas price to issue funds with
...
@@ -324,33 +326,30 @@ func (f *faucet) apiHandler(conn *websocket.Conn) {
...
@@ -324,33 +326,30 @@ func (f *faucet) apiHandler(conn *websocket.Conn) {
nonce
uint64
nonce
uint64
err
error
err
error
)
)
for
{
for
head
==
nil
||
balance
==
nil
{
// Attempt to retrieve the stats, may error on no faucet connectivity
// Retrieve the current stats cached by the faucet
ctx
,
cancel
:=
context
.
WithTimeout
(
context
.
Background
(),
3
*
time
.
Second
)
f
.
lock
.
RLock
()
head
,
err
=
f
.
client
.
HeaderByNumber
(
ctx
,
nil
)
if
f
.
head
!=
nil
{
if
err
==
nil
{
head
=
types
.
CopyHeader
(
f
.
head
)
balance
,
err
=
f
.
client
.
BalanceAt
(
ctx
,
f
.
account
.
Address
,
head
.
Number
)
if
err
==
nil
{
nonce
,
err
=
f
.
client
.
NonceAt
(
ctx
,
f
.
account
.
Address
,
nil
)
}
}
}
cancel
()
if
f
.
balance
!=
nil
{
balance
=
new
(
big
.
Int
)
.
Set
(
f
.
balance
)
}
nonce
=
f
.
nonce
f
.
lock
.
RUnlock
()
// If stats retrieval failed, wait a bit and retry
if
head
==
nil
||
balance
==
nil
{
if
err
!=
nil
{
// Report the faucet offline until initial stats are ready
if
err
=
sendError
(
conn
,
errors
.
New
(
"Faucet offline
: "
+
err
.
Error
()
));
err
!=
nil
{
if
err
=
sendError
(
conn
,
errors
.
New
(
"Faucet offline
"
));
err
!=
nil
{
log
.
Warn
(
"Failed to send faucet error to client"
,
"err"
,
err
)
log
.
Warn
(
"Failed to send faucet error to client"
,
"err"
,
err
)
return
return
}
}
time
.
Sleep
(
3
*
time
.
Second
)
time
.
Sleep
(
3
*
time
.
Second
)
continue
}
}
// Initial stats reported successfully, proceed with user interaction
break
}
}
// Send over the initial stats and the latest header
// Send over the initial stats and the latest header
if
err
=
send
(
conn
,
map
[
string
]
interface
{}{
if
err
=
send
(
conn
,
map
[
string
]
interface
{}{
"funds"
:
balance
.
Div
(
balance
,
ether
),
"funds"
:
new
(
big
.
Int
)
.
Div
(
balance
,
ether
),
"funded"
:
nonce
,
"funded"
:
nonce
,
"peers"
:
f
.
stack
.
Server
()
.
PeerCount
(),
"peers"
:
f
.
stack
.
Server
()
.
PeerCount
(),
"requests"
:
f
.
reqs
,
"requests"
:
f
.
reqs
,
...
@@ -520,6 +519,47 @@ func (f *faucet) apiHandler(conn *websocket.Conn) {
...
@@ -520,6 +519,47 @@ func (f *faucet) apiHandler(conn *websocket.Conn) {
}
}
}
}
// refresh attempts to retrieve the latest header from the chain and extract the
// associated faucet balance and nonce for connectivity caching.
func
(
f
*
faucet
)
refresh
(
head
*
types
.
Header
)
error
{
// Ensure a state update does not run for too long
ctx
,
cancel
:=
context
.
WithTimeout
(
context
.
Background
(),
5
*
time
.
Second
)
defer
cancel
()
// If no header was specified, use the current chain head
var
err
error
if
head
==
nil
{
if
head
,
err
=
f
.
client
.
HeaderByNumber
(
ctx
,
nil
);
err
!=
nil
{
return
err
}
}
// Retrieve the balance, nonce and gas price from the current head
var
(
balance
*
big
.
Int
nonce
uint64
price
*
big
.
Int
)
if
balance
,
err
=
f
.
client
.
BalanceAt
(
ctx
,
f
.
account
.
Address
,
head
.
Number
);
err
!=
nil
{
return
err
}
if
nonce
,
err
=
f
.
client
.
NonceAt
(
ctx
,
f
.
account
.
Address
,
head
.
Number
);
err
!=
nil
{
return
err
}
if
price
,
err
=
f
.
client
.
SuggestGasPrice
(
ctx
);
err
!=
nil
{
return
err
}
// Everything succeeded, update the cached stats and eject old requests
f
.
lock
.
Lock
()
f
.
head
,
f
.
balance
=
head
,
balance
f
.
price
,
f
.
nonce
=
price
,
nonce
for
len
(
f
.
reqs
)
>
0
&&
f
.
reqs
[
0
]
.
Tx
.
Nonce
()
<
f
.
nonce
{
f
.
reqs
=
f
.
reqs
[
1
:
]
}
f
.
lock
.
Unlock
()
return
nil
}
// loop keeps waiting for interesting events and pushes them out to connected
// loop keeps waiting for interesting events and pushes them out to connected
// websockets.
// websockets.
func
(
f
*
faucet
)
loop
()
{
func
(
f
*
faucet
)
loop
()
{
...
@@ -537,45 +577,27 @@ func (f *faucet) loop() {
...
@@ -537,45 +577,27 @@ func (f *faucet) loop() {
go
func
()
{
go
func
()
{
for
head
:=
range
update
{
for
head
:=
range
update
{
// New chain head arrived, query the current stats and stream to clients
// New chain head arrived, query the current stats and stream to clients
var
(
timestamp
:=
time
.
Unix
(
head
.
Time
.
Int64
(),
0
)
balance
*
big
.
Int
if
time
.
Since
(
timestamp
)
>
time
.
Hour
{
nonce
uint64
log
.
Warn
(
"Skipping faucet refresh, head too old"
,
"number"
,
head
.
Number
,
"hash"
,
head
.
Hash
(),
"age"
,
common
.
PrettyAge
(
timestamp
))
price
*
big
.
Int
continue
err
error
)
ctx
,
cancel
:=
context
.
WithTimeout
(
context
.
Background
(),
5
*
time
.
Second
)
balance
,
err
=
f
.
client
.
BalanceAt
(
ctx
,
f
.
account
.
Address
,
head
.
Number
)
if
err
==
nil
{
nonce
,
err
=
f
.
client
.
NonceAt
(
ctx
,
f
.
account
.
Address
,
nil
)
if
err
==
nil
{
price
,
err
=
f
.
client
.
SuggestGasPrice
(
ctx
)
}
}
}
cancel
()
if
err
:=
f
.
refresh
(
head
);
err
!=
nil
{
// If querying the data failed, try for the next block
if
err
!=
nil
{
log
.
Warn
(
"Failed to update faucet state"
,
"block"
,
head
.
Number
,
"hash"
,
head
.
Hash
(),
"err"
,
err
)
log
.
Warn
(
"Failed to update faucet state"
,
"block"
,
head
.
Number
,
"hash"
,
head
.
Hash
(),
"err"
,
err
)
continue
continue
}
else
{
log
.
Info
(
"Updated faucet state"
,
"block"
,
head
.
Number
,
"hash"
,
head
.
Hash
(),
"balance"
,
balance
,
"nonce"
,
nonce
,
"price"
,
price
)
}
}
// Faucet state retrieved, update locally and send to clients
// Faucet state retrieved, update locally and send to clients
balance
=
new
(
big
.
Int
)
.
Div
(
balance
,
ether
)
f
.
lock
.
RLock
()
log
.
Info
(
"Updated faucet state"
,
"number"
,
head
.
Number
,
"hash"
,
head
.
Hash
(),
"age"
,
common
.
PrettyAge
(
timestamp
),
"balance"
,
f
.
balance
,
"nonce"
,
f
.
nonce
,
"price"
,
f
.
price
)
f
.
lock
.
Lock
()
balance
:=
new
(
big
.
Int
)
.
Div
(
f
.
balance
,
ether
)
f
.
price
,
f
.
nonce
=
price
,
nonce
peers
:=
f
.
stack
.
Server
()
.
PeerCount
()
for
len
(
f
.
reqs
)
>
0
&&
f
.
reqs
[
0
]
.
Tx
.
Nonce
()
<
f
.
nonce
{
f
.
reqs
=
f
.
reqs
[
1
:
]
}
f
.
lock
.
Unlock
()
f
.
lock
.
RLock
()
for
_
,
conn
:=
range
f
.
conns
{
for
_
,
conn
:=
range
f
.
conns
{
if
err
:=
send
(
conn
,
map
[
string
]
interface
{}{
if
err
:=
send
(
conn
,
map
[
string
]
interface
{}{
"funds"
:
balance
,
"funds"
:
balance
,
"funded"
:
f
.
nonce
,
"funded"
:
f
.
nonce
,
"peers"
:
f
.
stack
.
Server
()
.
PeerCount
()
,
"peers"
:
peers
,
"requests"
:
f
.
reqs
,
"requests"
:
f
.
reqs
,
},
time
.
Second
);
err
!=
nil
{
},
time
.
Second
);
err
!=
nil
{
log
.
Warn
(
"Failed to send stats to client"
,
"err"
,
err
)
log
.
Warn
(
"Failed to send stats to client"
,
"err"
,
err
)
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment