Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

P2P filtering functions #993

Merged
merged 2 commits into from
May 15, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

FEATURES

* baseapp now has settable functions for filtering peers by address/port & public key
* Gas consumption is now measured as transactions are executed
* Transactions which run out of gas stop execution and revert state changes
* A "simulate" query has been added to determine how much gas a transaction will need
Expand Down
45 changes: 42 additions & 3 deletions baseapp/baseapp.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,11 @@ type BaseApp struct {
txGasLimit sdk.Gas // per-transaction gas limit

// may be nil
initChainer sdk.InitChainer // initialize state with validators and state blob
beginBlocker sdk.BeginBlocker // logic to run before any txs
endBlocker sdk.EndBlocker // logic to run after all txs, and to determine valset changes
initChainer sdk.InitChainer // initialize state with validators and state blob
beginBlocker sdk.BeginBlocker // logic to run before any txs
endBlocker sdk.EndBlocker // logic to run after all txs, and to determine valset changes
addrPeerFilter sdk.PeerFilter // filter peers by address and port
pubkeyPeerFilter sdk.PeerFilter // filter peers by public key

//--------------------
// Volatile
Expand Down Expand Up @@ -142,6 +144,12 @@ func (app *BaseApp) SetEndBlocker(endBlocker sdk.EndBlocker) {
func (app *BaseApp) SetAnteHandler(ah sdk.AnteHandler) {
app.anteHandler = ah
}
func (app *BaseApp) SetAddrPeerFilter(pf sdk.PeerFilter) {
app.addrPeerFilter = pf
}
func (app *BaseApp) SetPubKeyPeerFilter(pf sdk.PeerFilter) {
app.pubkeyPeerFilter = pf
}
func (app *BaseApp) Router() Router { return app.router }

// load latest application version
Expand Down Expand Up @@ -282,6 +290,22 @@ func (app *BaseApp) InitChain(req abci.RequestInitChain) (res abci.ResponseInitC
return
}

// Filter peers by address / port
func (app *BaseApp) FilterPeerByAddrPort(info string) abci.ResponseQuery {
if app.addrPeerFilter != nil {
return app.addrPeerFilter(info)
}
return abci.ResponseQuery{}
}

// Filter peers by public key
func (app *BaseApp) FilterPeerByPubKey(info string) abci.ResponseQuery {
if app.pubkeyPeerFilter != nil {
return app.pubkeyPeerFilter(info)
}
return abci.ResponseQuery{}
}

// Implements ABCI.
// Delegates to CommitMultiStore if it implements Queryable
func (app *BaseApp) Query(req abci.RequestQuery) (res abci.ResponseQuery) {
Expand Down Expand Up @@ -318,6 +342,21 @@ func (app *BaseApp) Query(req abci.RequestQuery) (res abci.ResponseQuery) {
req.Path = req.Path[6:] // slice off "/store"
return queryable.Query(req)
}
// "/p2p" prefix for p2p queries
if strings.HasPrefix(path, "/p2p") {
path = path[4:]
if strings.HasPrefix(path, "/filter") {
path = path[7:]
if strings.HasPrefix(path, "/addr") {
path = path[6:]
return app.FilterPeerByAddrPort(path)
}
if strings.HasPrefix(path, "/pubkey") {
path = path[8:]
return app.FilterPeerByPubKey(path)
}
}
}
msg := "unknown query path"
return sdk.ErrUnknownRequest(msg).QueryResult()
}
Expand Down
33 changes: 33 additions & 0 deletions baseapp/baseapp_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -399,6 +399,39 @@ func TestQuery(t *testing.T) {
assert.Equal(t, value, res.Value)
}

// Test p2p filter queries
func TestP2PQuery(t *testing.T) {
app := newBaseApp(t.Name())

// make a cap key and mount the store
capKey := sdk.NewKVStoreKey("main")
app.MountStoresIAVL(capKey)
err := app.LoadLatestVersion(capKey) // needed to make stores non-nil
assert.Nil(t, err)

app.SetAddrPeerFilter(func(addrport string) abci.ResponseQuery {
require.Equal(t, "1.1.1.1:8000", addrport)
return abci.ResponseQuery{Code: uint32(3)}
})

app.SetPubKeyPeerFilter(func(pubkey string) abci.ResponseQuery {
require.Equal(t, "testpubkey", pubkey)
return abci.ResponseQuery{Code: uint32(4)}
})

addrQuery := abci.RequestQuery{
Path: "/p2p/filter/addr/1.1.1.1:8000",
}
res := app.Query(addrQuery)
require.Equal(t, uint32(3), res.Code)

pubkeyQuery := abci.RequestQuery{
Path: "/p2p/filter/pubkey/testpubkey",
}
res = app.Query(pubkeyQuery)
require.Equal(t, uint32(4), res.Code)
}

//----------------------
// TODO: clean this up

Expand Down
3 changes: 3 additions & 0 deletions types/abci.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,6 @@ type BeginBlocker func(ctx Context, req abci.RequestBeginBlock) abci.ResponseBeg

// run code after the transactions in a block and return updates to the validator set
type EndBlocker func(ctx Context, req abci.RequestEndBlock) abci.ResponseEndBlock

// respond to p2p filtering queries from Tendermint
type PeerFilter func(info string) abci.ResponseQuery