Initial commit.
Add publishBlockV2 client call implementation. Add support of 415 error.
This commit is contained in:
parent
484f48953b
commit
86af562deb
|
@ -165,44 +165,80 @@ proc publishSszBlock*(
|
|||
extraHeaders = @[("eth-consensus-version", consensus)])
|
||||
return resp
|
||||
|
||||
proc publishBlockV2Plain(body: phase0.SignedBeaconBlock): RestPlainResponse {.
|
||||
rest, endpoint: "/eth/v2/beacon/blocks",
|
||||
meth: MethodPost.}
|
||||
proc publishBlockV2Plain(
|
||||
broadcast_validation: Option[BroadcastValidationType],
|
||||
body: phase0.SignedBeaconBlock
|
||||
): RestPlainResponse {.
|
||||
rest, endpoint: "/eth/v2/beacon/blocks", meth: MethodPost.}
|
||||
## https://ethereum.github.io/beacon-APIs/#/Beacon/publishBlockV2
|
||||
|
||||
proc publishBlockV2Plain(body: altair.SignedBeaconBlock): RestPlainResponse {.
|
||||
rest, endpoint: "/eth/v2/beacon/blocks",
|
||||
meth: MethodPost.}
|
||||
proc publishBlockV2Plain(
|
||||
broadcast_validation: Option[BroadcastValidationType],
|
||||
body: altair.SignedBeaconBlock
|
||||
): RestPlainResponse {.
|
||||
rest, endpoint: "/eth/v2/beacon/blocks", meth: MethodPost.}
|
||||
## https://ethereum.github.io/beacon-APIs/#/Beacon/publishBlockV2
|
||||
|
||||
proc publishBlockV2Plain(body: bellatrix.SignedBeaconBlock): RestPlainResponse {.
|
||||
rest, endpoint: "/eth/v2/beacon/blocks",
|
||||
meth: MethodPost.}
|
||||
proc publishBlockV2Plain(
|
||||
broadcast_validation: Option[BroadcastValidationType],
|
||||
body: bellatrix.SignedBeaconBlock
|
||||
): RestPlainResponse {.
|
||||
rest, endpoint: "/eth/v2/beacon/blocks", meth: MethodPost.}
|
||||
## https://ethereum.github.io/beacon-APIs/#/Beacon/publishBlockV2
|
||||
|
||||
proc publishBlockV2Plain(body: capella.SignedBeaconBlock): RestPlainResponse {.
|
||||
rest, endpoint: "/eth/v2/beacon/blocks",
|
||||
meth: MethodPost.}
|
||||
proc publishBlockV2Plain(
|
||||
broadcast_validation: Option[BroadcastValidationType],
|
||||
body: capella.SignedBeaconBlock
|
||||
): RestPlainResponse {.
|
||||
rest, endpoint: "/eth/v2/beacon/blocks", meth: MethodPost.}
|
||||
## https://ethereum.github.io/beacon-APIs/#/Beacon/publishBlockV2
|
||||
|
||||
proc publishBlockV2Plain(body: DenebSignedBlockContents): RestPlainResponse {.
|
||||
rest, endpoint: "/eth/v2/beacon/blocks",
|
||||
meth: MethodPost.}
|
||||
proc publishBlockV2Plain(
|
||||
broadcast_validation: Option[BroadcastValidationType],
|
||||
body: DenebSignedBlockContents
|
||||
): RestPlainResponse {.
|
||||
rest, endpoint: "/eth/v2/beacon/blocks", meth: MethodPost.}
|
||||
## https://ethereum.github.io/beacon-APIs/#/Beacon/publishBlockV2
|
||||
|
||||
proc publishBlockV2Plain(
|
||||
broadcast_validation: Option[BroadcastValidationType],
|
||||
body: ElectraSignedBlockContents
|
||||
): RestPlainResponse {.
|
||||
rest, endpoint: "/eth/v2/beacon/blocks", meth: MethodPost.}
|
||||
## https://ethereum.github.io/beacon-APIs/#/Beacon/publishBlockV2
|
||||
|
||||
proc publishBlockV2*(
|
||||
client: RestClientRef,
|
||||
blck: phase0.SignedBeaconBlock | altair.SignedBeaconBlock |
|
||||
bellatrix.SignedBeaconBlock | capella.SignedBeaconBlock |
|
||||
deneb.SignedBeaconBlock
|
||||
): Future[RestPlainResponse] {.async} =
|
||||
client: RestClientRef,
|
||||
blck: phase0.SignedBeaconBlock | altair.SignedBeaconBlock |
|
||||
bellatrix.SignedBeaconBlock | capella.SignedBeaconBlock |
|
||||
DenebSignedBlockContents | ElectraSignedBlockContents,
|
||||
validation: Opt[BroadcastValidationType] =
|
||||
Opt.none(BroadcastValidationType),
|
||||
contentType: Opt[MediaType] = Opt.none(MediaType)
|
||||
): Future[RestPlainResponse] {.
|
||||
async: (raises: [CancelledError, RestEncodingError, RestDnsResolveError,
|
||||
RestCommunicationError])} =
|
||||
## https://ethereum.github.io/beacon-APIs/#/Beacon/publishBlockV2
|
||||
let
|
||||
consensus = typeof(blck).kind.toString()
|
||||
resp = await client.publishBlockV2Plain(
|
||||
blck, extraHeaders = @[
|
||||
("eth-consensus-version", consensus),
|
||||
("broadcast_validation", "gossip")])
|
||||
return resp
|
||||
consensus =
|
||||
when blck is DenebSignedBlockContents:
|
||||
toString(ConsensusFork.Deneb)
|
||||
elif blck is ElectraSignedBlockContents:
|
||||
toString(ConsensusFork.Electra)
|
||||
else:
|
||||
typeof(blck).kind.toString()
|
||||
mediaType = contentType.valueOr:
|
||||
ApplicationJsonMediaType
|
||||
broadcastValidation =
|
||||
if validation.isSome():
|
||||
some[BroadcastValidationType](validation.get())
|
||||
else:
|
||||
none[BroadcastValidationType]()
|
||||
await client.publishBlockV2Plain(
|
||||
broadcastValidation,
|
||||
blck,
|
||||
restContentType = $mediaType,
|
||||
extraHeaders = @[("eth-consensus-version", consensus)])
|
||||
|
||||
proc publishBlindedBlock*(body: phase0.SignedBeaconBlock): RestPlainResponse {.
|
||||
rest, endpoint: "/eth/v1/beacon/blinded_blocks",
|
||||
|
|
|
@ -25,6 +25,8 @@ const
|
|||
ResponseECNotInSyncError* = "Execution client not in sync"
|
||||
ResponseNotImplementedError =
|
||||
"Received endpoint not implemented error response"
|
||||
ResponseUnsupportedContentTypeError =
|
||||
"Server does not support provided content type"
|
||||
|
||||
type
|
||||
ApiResponse*[T] = Result[T, string]
|
||||
|
@ -761,6 +763,11 @@ template handle404(): untyped {.dirty.} =
|
|||
node.updateStatus(RestBeaconNodeStatus.Incompatible, failure)
|
||||
failures.add(failure)
|
||||
|
||||
template handle415(): untyped {.dirty.} =
|
||||
let failure = ApiNodeFailure.init(ApiFailure.NotSupportedContentType,
|
||||
RequestName, strategy, node, response.status, response.getErrorMessage())
|
||||
failures.add(failure)
|
||||
|
||||
template handle500(): untyped {.dirty.} =
|
||||
let failure = ApiNodeFailure.init(ApiFailure.Internal, RequestName,
|
||||
strategy, node, response.status, response.getErrorMessage())
|
||||
|
@ -2284,6 +2291,9 @@ proc publishBlock*(
|
|||
of 400:
|
||||
handle400()
|
||||
ApiResponse[bool].err(ResponseInvalidError)
|
||||
of 415:
|
||||
handle415()
|
||||
ApiResponse[bool].err(ResponseUnsupportedContentTypeError)
|
||||
of 500:
|
||||
handle500()
|
||||
ApiResponse[bool].err(ResponseInternalError)
|
||||
|
@ -2333,6 +2343,127 @@ proc publishBlock*(
|
|||
of 400:
|
||||
handle400()
|
||||
false
|
||||
of 415:
|
||||
handle415()
|
||||
false
|
||||
of 500:
|
||||
handle500()
|
||||
false
|
||||
of 503:
|
||||
handle503()
|
||||
false
|
||||
else:
|
||||
handleUnexpectedCode()
|
||||
false
|
||||
|
||||
raise (ref ValidatorApiError)(
|
||||
msg: "Failed to publish block", data: failures)
|
||||
|
||||
proc publishBlockV2*(
|
||||
vc: ValidatorClientRef,
|
||||
data: RestPublishedSignedBlockContents,
|
||||
validation: BroadcastValidationType,
|
||||
contentType: MediaType,
|
||||
strategy: ApiStrategyKind
|
||||
): Future[bool] {.async.} =
|
||||
const
|
||||
RequestName = "publishBlockV2"
|
||||
BlockBroadcasted = "Block not passed validation, but still published"
|
||||
|
||||
var failures: seq[ApiNodeFailure]
|
||||
|
||||
case strategy
|
||||
of ApiStrategyKind.First, ApiStrategyKind.Best:
|
||||
let res = block:
|
||||
vc.firstSuccessParallel(RestPlainResponse,
|
||||
bool,
|
||||
SlotDuration,
|
||||
ViableNodeStatus,
|
||||
{BeaconNodeRole.BlockProposalPublish}):
|
||||
case data.kind
|
||||
of ConsensusFork.Phase0:
|
||||
publishBlockV2(it, data.phase0Data)
|
||||
of ConsensusFork.Altair:
|
||||
publishBlockV2(it, data.altairData)
|
||||
of ConsensusFork.Bellatrix:
|
||||
publishBlockV2(it, data.bellatrixData)
|
||||
of ConsensusFork.Capella:
|
||||
publishBlockV2(it, data.capellaData)
|
||||
of ConsensusFork.Deneb:
|
||||
publishBlockV2(it, data.denebData)
|
||||
of ConsensusFork.Electra:
|
||||
publishBlockV2(it, data.electraData)
|
||||
do:
|
||||
if apiResponse.isErr():
|
||||
handleCommunicationError()
|
||||
ApiResponse[bool].err(apiResponse.error)
|
||||
else:
|
||||
let response = apiResponse.get()
|
||||
case response.status:
|
||||
of 200:
|
||||
ApiResponse[bool].ok(true)
|
||||
of 202:
|
||||
debug BlockBroadcasted, node = node,
|
||||
blck = shortLog(ForkedSignedBeaconBlock.init(data))
|
||||
ApiResponse[bool].ok(true)
|
||||
of 400:
|
||||
handle400()
|
||||
ApiResponse[bool].err(ResponseInvalidError)
|
||||
of 415:
|
||||
handle415()
|
||||
ApiResponse[bool].err(ResponseUnsupportedContentTypeError)
|
||||
of 500:
|
||||
handle500()
|
||||
ApiResponse[bool].err(ResponseInternalError)
|
||||
of 503:
|
||||
handle503()
|
||||
ApiResponse[bool].err(ResponseNoSyncError)
|
||||
else:
|
||||
handleUnexpectedCode()
|
||||
ApiResponse[bool].err(ResponseUnexpectedError)
|
||||
|
||||
if res.isErr():
|
||||
raise (ref ValidatorApiError)(msg: res.error, data: failures)
|
||||
return res.get()
|
||||
|
||||
of ApiStrategyKind.Priority:
|
||||
vc.firstSuccessSequential(RestPlainResponse,
|
||||
SlotDuration,
|
||||
ViableNodeStatus,
|
||||
{BeaconNodeRole.BlockProposalPublish}):
|
||||
case data.kind
|
||||
of ConsensusFork.Phase0:
|
||||
publishBlock(it, data.phase0Data)
|
||||
of ConsensusFork.Altair:
|
||||
publishBlock(it, data.altairData)
|
||||
of ConsensusFork.Bellatrix:
|
||||
publishBlock(it, data.bellatrixData)
|
||||
of ConsensusFork.Capella:
|
||||
publishBlock(it, data.capellaData)
|
||||
of ConsensusFork.Deneb:
|
||||
publishBlock(it, data.denebData)
|
||||
of ConsensusFork.Electra:
|
||||
publishBlock(it, data.electraData)
|
||||
|
||||
do:
|
||||
if apiResponse.isErr():
|
||||
handleCommunicationError()
|
||||
false
|
||||
else:
|
||||
let response = apiResponse.get()
|
||||
case response.status:
|
||||
of 200:
|
||||
return true
|
||||
of 202:
|
||||
debug BlockBroadcasted, node = node,
|
||||
blck = shortLog(ForkedSignedBeaconBlock.init(data))
|
||||
return true
|
||||
of 400:
|
||||
handle400()
|
||||
false
|
||||
of 415:
|
||||
handle415()
|
||||
false
|
||||
of 500:
|
||||
handle500()
|
||||
false
|
||||
|
|
|
@ -393,7 +393,12 @@ proc publishBlockV3(vc: ValidatorClientRef, currentSlot, slot: Slot,
|
|||
res =
|
||||
try:
|
||||
debug "Sending block"
|
||||
await vc.publishBlock(signedBlockContents, ApiStrategyKind.First)
|
||||
await vc.publishBlockV2(
|
||||
signedBlockContents,
|
||||
BroadcastValidationType.Gossip,
|
||||
ApplicationJsonMediaType,
|
||||
ApiStrategyKind.First
|
||||
)
|
||||
except ValidatorApiError as exc:
|
||||
warn "Unable to publish block", reason = exc.getFailureReason()
|
||||
return false
|
||||
|
|
|
@ -242,7 +242,8 @@ type
|
|||
|
||||
ApiFailure* {.pure.} = enum
|
||||
Communication, Invalid, NotFound, OptSynced, NotSynced, Internal,
|
||||
NotImplemented, UnexpectedCode, UnexpectedResponse, NoError
|
||||
NotImplemented, UnexpectedCode, UnexpectedResponse, NotSupportedContentType,
|
||||
NoError
|
||||
|
||||
ApiNodeFailure* = object
|
||||
node*: BeaconNodeServerRef
|
||||
|
@ -377,6 +378,7 @@ proc `$`*(failure: ApiFailure): string =
|
|||
of ApiFailure.UnexpectedCode: "unexpected-code"
|
||||
of ApiFailure.UnexpectedResponse: "unexpected-data"
|
||||
of ApiFailure.NoError: "status-update"
|
||||
of ApiFailure.NotSupportedContentType: "not-supported-content-type"
|
||||
|
||||
proc getNodeCounts*(vc: ValidatorClientRef): BeaconNodesCounters =
|
||||
var res = BeaconNodesCounters()
|
||||
|
|
Loading…
Reference in New Issue