Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
M
mybee
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Boards
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
vicotor
mybee
Commits
982d73c3
Unverified
Commit
982d73c3
authored
Jun 21, 2021
by
Ralph Pichler
Committed by
GitHub
Jun 21, 2021
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
feat: add greylist to sender matcher (#2161)
parent
55518ade
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
119 additions
and
17 deletions
+119
-17
export_test.go
pkg/transaction/export_test.go
+12
-0
sender_matcher.go
pkg/transaction/sender_matcher.go
+30
-17
sender_matcher_test.go
pkg/transaction/sender_matcher_test.go
+77
-0
No files found.
pkg/transaction/export_test.go
View file @
982d73c3
...
...
@@ -4,6 +4,18 @@
package
transaction
import
"time"
var
(
StoredTransactionKey
=
storedTransactionKey
)
func
(
s
*
Matcher
)
SetTimeNow
(
f
func
()
time
.
Time
)
{
s
.
timeNow
=
f
}
func
(
s
*
Matcher
)
SetTime
(
k
int64
)
{
s
.
SetTimeNow
(
func
()
time
.
Time
{
return
time
.
Unix
(
k
,
0
)
})
}
pkg/transaction/sender_matcher.go
View file @
982d73c3
...
...
@@ -19,28 +19,30 @@ type Matcher struct {
backend
Backend
storage
storage
.
StateStorer
signer
types
.
Signer
timeNow
func
()
time
.
Time
}
const
(
overlayPrefix
=
"verified_overlay_"
)
func
peerOverlayKey
(
peer
swarm
.
Address
)
string
{
return
fmt
.
Sprintf
(
"%s%s
"
,
overlayPrefix
,
peer
.
String
())
func
peerOverlayKey
(
peer
swarm
.
Address
,
txHash
common
.
Hash
)
string
{
return
fmt
.
Sprintf
(
"%s%s
_%s"
,
overlayPrefix
,
peer
.
String
(),
txHash
.
String
())
}
var
(
ErrTransactionNotFound
=
errors
.
New
(
"transaction not found"
)
ErrTransactionPending
=
errors
.
New
(
"transaction in pending status"
)
ErrTransactionSenderInvalid
=
errors
.
New
(
"invalid transaction sender"
)
ErrGreylisted
=
errors
.
New
(
"overlay and transaction greylisted"
)
ErrBlockHashMismatch
=
errors
.
New
(
"block hash mismatch"
)
ErrOverlayMismatch
=
errors
.
New
(
"overlay mismatch"
)
)
type
overlayVerification
struct
{
n
extBlockHash
[]
byte
v
erified
bool
t
imeStamp
time
.
Time
N
extBlockHash
[]
byte
V
erified
bool
T
imeStamp
time
.
Time
}
func
NewMatcher
(
backend
Backend
,
signer
types
.
Signer
,
storage
storage
.
StateStorer
)
*
Matcher
{
...
...
@@ -48,23 +50,34 @@ func NewMatcher(backend Backend, signer types.Signer, storage storage.StateStore
storage
:
storage
,
backend
:
backend
,
signer
:
signer
,
timeNow
:
time
.
Now
,
}
}
func
(
m
*
Matcher
)
Matches
(
ctx
context
.
Context
,
tx
[]
byte
,
networkID
uint64
,
senderOverlay
swarm
.
Address
)
([]
byte
,
error
)
{
var
val
overlayVerification
incomingTx
:=
common
.
BytesToHash
(
tx
)
err
:=
m
.
storage
.
Get
(
peerOverlayKey
(
senderOverlay
),
&
val
)
if
err
!=
nil
&&
!
errors
.
Is
(
err
,
storage
.
ErrNotFound
)
{
return
nil
,
err
}
else
if
val
.
verified
{
var
val
overlayVerification
err
:=
m
.
storage
.
Get
(
peerOverlayKey
(
senderOverlay
,
incomingTx
),
&
val
)
if
err
!=
nil
{
if
!
errors
.
Is
(
err
,
storage
.
ErrNotFound
)
{
return
nil
,
err
}
}
else
if
val
.
Verified
{
// add cache invalidation
return
val
.
nextBlockHash
,
nil
return
val
.
NextBlockHash
,
nil
}
else
if
val
.
TimeStamp
.
Add
(
5
*
time
.
Minute
)
.
After
(
m
.
timeNow
())
{
return
nil
,
ErrGreylisted
}
incomingTx
:=
common
.
BytesToHash
(
tx
)
err
=
m
.
storage
.
Put
(
peerOverlayKey
(
senderOverlay
,
incomingTx
),
&
overlayVerification
{
TimeStamp
:
m
.
timeNow
(),
Verified
:
false
,
})
if
err
!=
nil
{
return
nil
,
err
}
nTx
,
isPending
,
err
:=
m
.
backend
.
TransactionByHash
(
ctx
,
incomingTx
)
if
err
!=
nil
{
...
...
@@ -104,10 +117,10 @@ func (m *Matcher) Matches(ctx context.Context, tx []byte, networkID uint64, send
return
nil
,
ErrOverlayMismatch
}
err
=
m
.
storage
.
Put
(
peerOverlayKey
(
senderOverlay
),
&
overlayVerification
{
timeStamp
:
time
.
Now
(),
v
erified
:
true
,
n
extBlockHash
:
nextBlockHash
,
err
=
m
.
storage
.
Put
(
peerOverlayKey
(
senderOverlay
,
incomingTx
),
&
overlayVerification
{
TimeStamp
:
m
.
time
Now
(),
V
erified
:
true
,
N
extBlockHash
:
nextBlockHash
,
})
if
err
!=
nil
{
...
...
pkg/transaction/sender_matcher_test.go
View file @
982d73c3
...
...
@@ -137,6 +137,83 @@ func TestMatchesSender(t *testing.T) {
t
.
Fatalf
(
"expected match"
)
}
})
t
.
Run
(
"cached"
,
func
(
t
*
testing
.
T
)
{
trxBlock
:=
common
.
HexToHash
(
"0x2"
)
nextBlockHeader
:=
&
types
.
Header
{
ParentHash
:
trxBlock
,
}
calls
:=
0
trxReceipt
:=
backendmock
.
WithTransactionReceiptFunc
(
func
(
ctx
context
.
Context
,
txHash
common
.
Hash
)
(
*
types
.
Receipt
,
error
)
{
calls
++
return
&
types
.
Receipt
{
BlockNumber
:
big
.
NewInt
(
0
),
BlockHash
:
trxBlock
,
},
nil
})
headerByNum
:=
backendmock
.
WithHeaderbyNumberFunc
(
func
(
ctx
context
.
Context
,
number
*
big
.
Int
)
(
*
types
.
Header
,
error
)
{
calls
++
return
nextBlockHeader
,
nil
})
txByHash
:=
backendmock
.
WithTransactionByHashFunc
(
func
(
ctx
context
.
Context
,
txHash
common
.
Hash
)
(
*
types
.
Transaction
,
bool
,
error
)
{
calls
++
return
signedTx
,
false
,
nil
})
signer
:=
&
mockSigner
{
addr
:
common
.
HexToAddress
(
"0xff"
),
}
matcher
:=
transaction
.
NewMatcher
(
backendmock
.
New
(
trxReceipt
,
headerByNum
,
txByHash
),
signer
,
statestore
.
NewStateStore
())
senderOverlay
:=
crypto
.
NewOverlayFromEthereumAddress
(
signer
.
addr
.
Bytes
(),
0
,
nextBlockHeader
.
Hash
()
.
Bytes
())
_
,
err
:=
matcher
.
Matches
(
context
.
Background
(),
trx
,
0
,
senderOverlay
)
if
err
!=
nil
{
t
.
Fatalf
(
"expected match"
)
}
_
,
err
=
matcher
.
Matches
(
context
.
Background
(),
trx
,
0
,
senderOverlay
)
if
err
!=
nil
{
t
.
Fatalf
(
"expected match"
)
}
if
calls
!=
3
{
t
.
Fatal
(
"too many calls"
)
}
})
t
.
Run
(
"greylisted"
,
func
(
t
*
testing
.
T
)
{
txByHash
:=
backendmock
.
WithTransactionByHashFunc
(
func
(
ctx
context
.
Context
,
txHash
common
.
Hash
)
(
*
types
.
Transaction
,
bool
,
error
)
{
return
nil
,
false
,
errors
.
New
(
"transaction not found by hash"
)
})
matcher
:=
transaction
.
NewMatcher
(
backendmock
.
New
(
txByHash
),
nil
,
statestore
.
NewStateStore
())
matcher
.
SetTime
(
0
)
_
,
err
:=
matcher
.
Matches
(
context
.
Background
(),
trx
,
0
,
swarm
.
NewAddress
([]
byte
{}))
if
!
errors
.
Is
(
err
,
transaction
.
ErrTransactionNotFound
)
{
t
.
Fatalf
(
"bad error type, want %v, got %v"
,
transaction
.
ErrTransactionNotFound
,
err
)
}
_
,
err
=
matcher
.
Matches
(
context
.
Background
(),
trx
,
0
,
swarm
.
NewAddress
([]
byte
{}))
if
!
errors
.
Is
(
err
,
transaction
.
ErrGreylisted
)
{
t
.
Fatalf
(
"bad error type, want %v, got %v"
,
transaction
.
ErrGreylisted
,
err
)
}
// greylist expires
matcher
.
SetTime
(
5
*
60
)
_
,
err
=
matcher
.
Matches
(
context
.
Background
(),
trx
,
0
,
swarm
.
NewAddress
([]
byte
{}))
if
!
errors
.
Is
(
err
,
transaction
.
ErrTransactionNotFound
)
{
t
.
Fatalf
(
"bad error type, want %v, got %v"
,
transaction
.
ErrTransactionNotFound
,
err
)
}
})
}
type
mockSigner
struct
{
...
...
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