-
Notifications
You must be signed in to change notification settings - Fork 128
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
api: add address/{address}/exists endpoint #1714
Conversation
Provides access to the existsaddresses RPC and parses the result.
d1e7d74
to
ba839cf
Compare
I prefer RPC these days anyway, so that's good. |
mask := binary.LittleEndian.Uint64(append(b, make([]byte, 8-len(b))...)) | ||
exists := make([]bool, 0, len(addresses)) | ||
for n := range addresses { | ||
exists = append(exists, (mask&(1<<uint8(n))) != 0) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good. My only concern is that maxExistAddrs
cannot be more than 64 because of this, and there's no check on maxExistAddrs
. I worry about someone bumping up maxExistAddrs
in the future without understanding it would lead to a panic in make
here when >64 addresses get passed, especially because it might appear to work OK in many cases.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should I just document maxExistAddr
better?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yah, that's cool. I think a note there not to go beyond 64 without modifying addressExists (or whatever) would be sufficient to prevent future breakage.
middleware/apimiddleware.go
Outdated
// GetAddressRawCtx returns a slice of addresses parsed from the {address} URL | ||
// parameter. Multiple comma-delimited address strings can be specified. | ||
func GetAddressRawCtx(r *http.Request, activeNetParams *chaincfg.Params, maxAddrs int) ([]dcrutil.Address, error) { | ||
addressStrs, err := addressStrings(r, maxAddrs) | ||
if err != nil { | ||
return nil, err | ||
} | ||
addresses := make([]dcrutil.Address, 0, len(addressStrs)) | ||
for _, addrStr := range addressStrs { | ||
addr, err := dcrutil.DecodeAddress(addrStr, activeNetParams) | ||
if err != nil { | ||
return nil, fmt.Errorf("invalid address '%v' for this network: %v", | ||
addrStr, err) | ||
} | ||
addresses = append(addresses, addr) | ||
} | ||
return addresses, nil | ||
} | ||
|
||
// addressStrings retrieves the CtxAddress data from the request context. If not | ||
// set, an error is generated. The CtxAddress string data may be a | ||
// comma-separated list of addresses, subject to the maxAddrs limit. | ||
func addressStrings(r *http.Request, maxAddrs int) ([]string, error) { | ||
addressStr, ok := r.Context().Value(CtxAddress).(string) | ||
if !ok || len(addressStr) == 0 { | ||
apiLog.Trace("address not set") | ||
return nil, fmt.Errorf("address not set") | ||
} | ||
addressStrs := strings.Split(addressStr, ",") | ||
if len(addressStrs) > maxAddrs { | ||
return nil, fmt.Errorf("maximum of %d addresses allowed", maxAddrs) | ||
} | ||
|
||
return addressStrs, nil | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice. Good validation. Although I'm thinking it could be even better to have this further up in the request handling chain, where CtxAddress
is set (middleware.AddressPathCtx
) to preempt the http handlers entirely if any of the addresses are invalid. If this opens a can of worms or becomes a major overhaul of all the /addr/...
endpoints, let's skip it though... just a thought.
It's basically the idea applied in the new indent middleware - validate the url bits and call next.ServerHTTP
otherwise http.Error
so that no other middlewares, subrouters, or any parts of the routed handler actually have to run if validation fails.
{ | ||
testName: "not_set", | ||
args: args{2, nil}, | ||
want: nil, | ||
wantErr: true, | ||
errMsg: "address not set", | ||
}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This was not very useful because the URL reduced to "/address/", which would be a different handler so chi was just returning a 404.
Provides access to the
existsaddresses
RPC call and parses the result to a[]bool
. Allows multiple comma-separated addresses to be specified in the same way as theaddrs
insight endpoints. Limited to 64 addresses, mostly because it simplifies parsing and use of the RPC result.The dcrd address existence index is enabled by default and seems to be quite fast. I did a little DB testing with the query
and it seems to be roughly the same speed on my system and network.