-
Notifications
You must be signed in to change notification settings - Fork 779
Proposervm API #4029
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
base: master
Are you sure you want to change the base?
Proposervm API #4029
Changes from 10 commits
f7bca02
46f9d06
5e3941a
d6873df
4e8239d
5ec65ff
a17f763
8bcd2b7
6e37eda
e250b85
463b936
79613f1
fa1802a
0e093df
44dd186
43e04c8
0875cb7
7ea6ee9
3ecd42f
dc586f4
bd2da2c
d1b1e5b
d7bb8bf
1057ba5
bb9b56d
07fdeb9
cc79175
19edd4d
a560a1d
8c96927
908ca7a
28c334b
a2744e8
66708ff
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
// Copyright (C) 2019-2024, Ava Labs, Inc. All rights reserved. | ||
// See the file LICENSE for licensing terms. | ||
|
||
package proposervm | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
|
||
"github.com/ava-labs/avalanchego/api" | ||
"github.com/ava-labs/avalanchego/ids" | ||
"github.com/ava-labs/avalanchego/utils/formatting" | ||
"github.com/ava-labs/avalanchego/utils/rpc" | ||
) | ||
|
||
var _ Client = (*client)(nil) | ||
|
||
type Client interface { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. who/what is consuming this interface? Usually in Golang, interfaces are declared where they're used, not where they're implemented. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The |
||
// GetProposedHeight returns the current height of this node's proposer VM. | ||
GetProposedHeight(ctx context.Context, options ...rpc.Option) (uint64, error) | ||
// GetProposerBlockWrapper returns the ProposerVM block wrapper | ||
GetProposerBlockWrapper(ctx context.Context, proposerID ids.ID, options ...rpc.Option) ([]byte, error) | ||
} | ||
|
||
type client struct { | ||
requester rpc.EndpointRequester | ||
} | ||
|
||
// NewClient returns a Client for interacting with the ProposerVM API. | ||
// The provided blockchainName should be the blockchainID or an alias (e.g. "P" for the P-Chain). | ||
func NewClient(uri string, blockchainName string) Client { | ||
return &client{ | ||
requester: rpc.NewEndpointRequester(uri + fmt.Sprintf("/ext/bc/%s/proposervm", blockchainName)), | ||
} | ||
} | ||
|
||
func (c *client) GetProposedHeight(ctx context.Context, options ...rpc.Option) (uint64, error) { | ||
res := &api.GetHeightResponse{} | ||
err := c.requester.SendRequest(ctx, "proposervm.getProposedHeight", struct{}{}, res, options...) | ||
return uint64(res.Height), err | ||
} | ||
|
||
func (c *client) GetProposerBlockWrapper(ctx context.Context, proposerID ids.ID, options ...rpc.Option) ([]byte, error) { | ||
res := &api.FormattedBlock{} | ||
if err := c.requester.SendRequest(ctx, "proposervm.getProposerBlockWrapper", &GetProposerBlockArgs{ | ||
ProposerID: proposerID, | ||
Encoding: formatting.Hex, | ||
}, res, options...); err != nil { | ||
return nil, err | ||
} | ||
return formatting.Decode(res.Encoding, res.Block) | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
// Copyright (C) 2019-2024, Ava Labs, Inc. All rights reserved. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. can we add tests to the code in this file? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Added unit tests |
||
// See the file LICENSE for licensing terms. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The lint job did not like including |
||
|
||
package proposervm | ||
|
||
import ( | ||
"encoding/json" | ||
"fmt" | ||
"net/http" | ||
|
||
"go.uber.org/zap" | ||
|
||
"github.com/ava-labs/avalanchego/api" | ||
"github.com/ava-labs/avalanchego/ids" | ||
"github.com/ava-labs/avalanchego/utils/formatting" | ||
|
||
avajson "github.com/ava-labs/avalanchego/utils/json" | ||
) | ||
|
||
type ProposerAPI struct { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What is the reason for having the proposerVM as a field instead of just adding the functions to the proposerVM VM? If we wish to isolate the VM object then it makes sense to add two functions or (an) interface(s) with:
and then it'll be easier to test. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thank you for the suggestion. Created the |
||
vm *VM | ||
} | ||
|
||
cam-schultz marked this conversation as resolved.
Show resolved
Hide resolved
|
||
func (p *ProposerAPI) GetProposedHeight(_ *http.Request, _ *struct{}, reply *api.GetHeightResponse) error { | ||
p.vm.ctx.Log.Debug("API called", | ||
zap.String("service", "proposervm"), | ||
zap.String("method", "getProposedHeight"), | ||
) | ||
p.vm.ctx.Lock.Lock() | ||
defer p.vm.ctx.Lock.Unlock() | ||
|
||
reply.Height = avajson.Uint64(p.vm.lastAcceptedHeight) | ||
return nil | ||
} | ||
|
||
// GetProposerBlockArgs is the parameters supplied to the GetProposerBlockWrapper API | ||
type GetProposerBlockArgs struct { | ||
ProposerID ids.ID `json:"proposerID"` | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I added this type rather than using the existing That said, I'm not sure what the best way to actually source the "Proposer ID" in the general case, since it's not exposed by the innerVM. Similarly, an endpoint to map Block hash -> Proposer ID seems like it would break encapsulation. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The word There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The explorer uses |
||
Encoding formatting.Encoding `json:"encoding"` | ||
} | ||
|
||
func (p *ProposerAPI) GetProposerBlockWrapper(r *http.Request, args *GetProposerBlockArgs, reply *api.GetBlockResponse) error { | ||
p.vm.ctx.Log.Debug("API called", | ||
zap.String("service", "proposervm"), | ||
zap.String("method", "getProposerBlockWrapper"), | ||
zap.String("proposerID", args.ProposerID.String()), | ||
zap.String("encoding", args.Encoding.String()), | ||
) | ||
p.vm.ctx.Lock.Lock() | ||
defer p.vm.ctx.Lock.Unlock() | ||
|
||
block, err := p.vm.GetBlock(r.Context(), args.ProposerID) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. am I reading this wrong and we're actually sending back the entire proposerVM block which also contains the inner VM block? If so, is it possible to only distill the proposerVM bytes? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The proposerVM fields will be add in this PR, and we will only return these useful fields in the PR. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Would it be possible to rebase this PR on top of that PR (3746) ? I am not a fan of leaving incomplete yet accessible APIs that are pending on other PRs. Also, rebasing this PR on top of that PR would make it possible to properly change the output of the API in this PR and not need to wait for a new PR. |
||
if err != nil { | ||
return err | ||
} | ||
reply.Encoding = args.Encoding | ||
|
||
var result any | ||
if args.Encoding == formatting.JSON { | ||
result = block | ||
} else { | ||
result, err = formatting.Encode(args.Encoding, block.Bytes()) | ||
if err != nil { | ||
return fmt.Errorf("couldn't encode block %s as %s: %w", args.ProposerID, args.Encoding, err) | ||
} | ||
} | ||
|
||
reply.Block, err = json.Marshal(result) | ||
return err | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,138 @@ | ||
The ProposerVM API allows clients to fetch information about a Snowman++ chain's ProposerVM. | ||
|
||
## Endpoint | ||
|
||
``` | ||
/ext/bc/{blockchainID}/proposervm | ||
``` | ||
|
||
## Format | ||
|
||
This API uses the `json 2.0` RPC format. | ||
|
||
## Methods | ||
|
||
### `proposervm.getProposedHeight` | ||
|
||
Returns this node's current proposer VM height. | ||
|
||
**Signature:** | ||
|
||
``` | ||
proposervm.getProposedHeight() -> | ||
{ | ||
height: int, | ||
} | ||
``` | ||
|
||
**Example Call:** | ||
|
||
```sh | ||
curl -X POST --data '{ | ||
"jsonrpc": "2.0", | ||
"method": "proposervm.getProposedHeight", | ||
"params": {}, | ||
"id": 1 | ||
}' -H 'content-type:application/json;' 127.0.0.1:9650/ext/bc/P/proposervm | ||
``` | ||
|
||
**Example Response:** | ||
|
||
```json | ||
{ | ||
"jsonrpc": "2.0", | ||
"result": { | ||
"height": "56" | ||
}, | ||
"id": 1 | ||
} | ||
``` | ||
|
||
### `proposervm.getProposerBlockWrapper` | ||
|
||
Get a block's ProposerVM wrapper by its proposer ID. | ||
|
||
**Signature:** | ||
|
||
``` | ||
proposervm.getProposerBlockWrapper({ | ||
proposerID: string | ||
encoding: string // optional | ||
}) -> { | ||
block: string, | ||
encoding: string | ||
} | ||
``` | ||
|
||
**Request:** | ||
|
||
- `proposerID` is the proposer ID. It should be in cb58 format. | ||
- `encoding` is the encoding format to use. Can be either `hex` or `json`. Defaults to `hex`. | ||
|
||
#### Hex Example | ||
|
||
**Example Call:** | ||
|
||
```sh | ||
curl -X POST --data '{ | ||
"jsonrpc": "2.0", | ||
"method": "proposervm.getProposerBlockWrapper", | ||
"params": { | ||
"proposerID": "owJxcaDMaehbqoib8FRP7MuPdfGpSdXqD4hjkBtW4vcCJzr2Y", | ||
"encoding": "hex" | ||
}, | ||
"id": 1 | ||
}' -H 'content-type:application/json;' 127.0.0.1:9650/ext/bc/C/proposervm | ||
``` | ||
|
||
**Example Response:** | ||
|
||
```json | ||
{ | ||
"jsonrpc":"2.0", | ||
"result":{ | ||
"block":"0x000000000000018a9f604b26237c49e54667b80e24433512774dd6bb8cd99032e927ae141dcd0000000068597a6d00000000000000000000053b308205373082031f020900baf3b5c5c6d0d14a300d06092a864886f70d01010b0500307f310b3009060355040613025553310b300906035504080c024e59310f300d06035504070c064974686163613110300e060355040a0c074176616c616273310e300c060355040b0c054765636b6f310c300a06035504030c036176613122302006092a864886f70d01090116137374657068656e406176616c6162732e6f72673020170d3139303730323136313231395a180f33303139303731303136313231395a303a310b3009060355040613025553310b300906035504080c024e593110300e060355040a0c074176616c616273310c300a06035504030c0361766130820222300d06092a864886f70d01010105000382020f003082020a0282020100dd4e847ad276ba36e47d892014332ccf5c934c59541b2f24f9fe2642889dc107861630185fc6925626259770cfb39c382926ec8211e8790e9e9963715eee4e8786de85985a438f09e3a5099d904294834d06f8494f4e9fd4b26b0f2fe240b303ea0595a93014b776c5d036e9cc32d30696b7f94b497a5d7e32ee473f193c5882f79667d26d47f9b628d7abfb08e0047a89e2b3ea9c7077d2c0d83d983dd42cf5024f016f6c36235d3ccd056028ae9e22a34a5c927fe298b3499754e3ddb4c0cc580699df0c07219f17a2f54fefdd06d3ede2942367c6afe84e59321653cd3e55e381b7c6ba3f8b12f40421e7fe86f2ac2602a3b7610f5dc4df368aefc7dfe37e1866bf334af9ac45abcf022e161c0abf241ca4f4419b6c909c19e12fd1b990dea7e0e04cd0ab2067709894765283879670d801b7558216c41ceef7d415a267afc40fde917857fe01a24ef04cee4737403511811562e5f9dcd1a7aca55ef8583dfb130e8173d691436a76fa48f596d5dd9d12e7cebaa85dffbc166b8600ab29ce44fef31ec4145ef0a8b8c0aa8e355862f561947111ef1448a473eed5acf8f461a1bacd52ddfae38024df357ca38f628e17e2c66b3323d89773a31ad3217d5e0abc268b12bd5db8e925a8ee9c0af190f220252d5cb7549c96e462740f42b28808abe1535d0092a8d598221a2bc92d6ba54df8d489f08df68d75e408aa2718aac30203010001300d06092a864886f70d01010b050003820201009039dc03ede448c41bdb40751cfa6d1347311ad7b0427dc9356365b03774d95c319290f544d2eba303c48bdea8bcfc24cb191a88f54de045925ffad24f045fcfd36d4f126c9a1534b886dc5c0f14f1b99bf68c2a3df97854132bd15a2b539a8cb57acab79a4a2d5501de4e642fc02b1024085cb5503f851749c2630fb3507c43139423a06a48e0476bd0ac5c8cd5385bfc16a13dd4f640da7b37d2c29062bae76c7f7d6a97c5e568252d4a323f0c5fd9edc000287b6de11d938e62bef2b08b9264f27afce4a0c760f96a92bd1b77d12197cc6995a34174c3de46e7ea043973b6370b277c289a7aedf7981031e4a82c763750db084636e3e37cc89aeeeaf6ffc30fda69429bb6e9a44346604d80b640f463395e76d94458b75712f2a9ab06712cda1f0cf973bbce04e90e765a9c43321246f583c623751e400bfa1922402b8c72180e44080cc333e8a1af2b7d6b4b229397329c2e5466fff2b18d2c43e8be808af73e9cf9667ece4468e3edd342438c63ae9786deeb021972de57abf93ca0e9ae635d3f7658a0bf317058032d9940da32db4e2434a7af707ed1d9c4a4c484ddde7e4469c372e4c02d08d224ec9c1e2c287dacbacb501b7e8b89f8e2c3fe2d585f5877a69e003c0a81789fa790d29a748b16537a7d23e2e3741b635ff89786325aa839b2d674839d1ffa5b0e9a571a865a28a0ddefe6c0ef81657b9521efed5edc00000373f90370f90298a057b43873f59d6e0ff493909e8373502eaa828f0eb4d7dbe999b855f9b895d88ca01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940100000000000000000000000000000000000000a0685dcd731e76c2e6a503df5759ab11b324f03c8f26090637ad4dbb26ad5522fba04efbaa764431eba396b9edba52f594a6660473432761931c98b49ef00467b87ea0d95b673818fa493deec414e01e610d97ee287c9421c8eff4102b1647c1a184e4b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010c83e4e1c082a4108468597a6db8560000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000880000000000000000a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421843b9aca0080808080a00000000000000000000000000000000000000000000000000000000000000000f8d0f866108534630b8a00825208948db97c7cece249c2b98bdc0226cc4c2a57bf52fc0180820a95a07ef0c6d54c839648ea6cfe191c37efc5ba9d9115695e061870b601c1ce647e75a03e066459cb0853a8d67f7b777753515b2ce627553a4d9b51b06ad6bdf3102b8ef866118534630b8a00825208948db97c7cece249c2b98bdc0226cc4c2a57bf52fc0180820a96a03a1c18eea77d4f08a29e482442ca2f2beb5bc8568e2768470ebdb6ae05382424a06e205ef2e0273c481f2e28a60e504575dba0714608601880d87906a98de41bb3c0808000000200bfcc7483e2c539c2d925a1b4eed65e2cbfae39e284be82d77ee86c078d1a1d4f54d8c46c6695d6619a589137eabcd4a8e93c94394c4d83458b122598b9d69f49f0c9e61b746ad46d91710c3475c97595d17c3ef1aa8c7e846fd8a231bdb68687a208ee752cd64ecf86288bec610688708e34d54ecb15ea4178e1dab8a74109ae1514240a08cddae9dc8ec6db17cfeffc2d0814e908e57676700c6fa3a4bbe1c84e537fd7d2f28491bf9ce3c5e57308027c198a3547ad9a23d365359b0c709c260abf6a04cdc59bcb4a65006c66c9cc2becae49e9275a2f3517260762a7b4c646121583590a25de74a924a66a43d2b1a6f09adfb664e552fc0b1b260594df57795b334c125627e112606d784790f6916dcb610f1e10a424f0ef8244cde7d2f0631e025b28d54f8a24003f3792b420a1eeb62a8a21a27e9eb7e3278b7e14dfc784e736ce2fad220ea9c2d97e98b451fd3a212b6b863a779d55a80ead284e49e0556792663e38316e7a31ac6b1915e96a1dd50924c48ffbb7d46df363baa3c8184457411577aa793cb3a9adef73301ecec8f7561f60a6187f13ed34d2e1756a7959fd5b10a4f753d07dd90022de2a2ea401e2516cd917a2a48c030e2cc0b2dfaa5dec82af18f6772462a5a58a9d128772b45f782c8a1854564158ed75531cc02d2050170de95147a8eb2b8364fb83d74722bee68e1654cf314d629599e3795617ff75c569bd", | ||
"encoding":"hex" | ||
}, | ||
"id":1 | ||
} | ||
``` | ||
|
||
#### JSON Example | ||
|
||
**Example Call:** | ||
|
||
```sh | ||
curl -X POST --data '{ | ||
"jsonrpc": "2.0", | ||
"method": "proposervm.getProposerBlockWrapper", | ||
"params": { | ||
"proposerID": "owJxcaDMaehbqoib8FRP7MuPdfGpSdXqD4hjkBtW4vcCJzr2Y", | ||
"encoding": "json" | ||
}, | ||
"id": 1 | ||
}' -H 'content-type:application/json;' 127.0.0.1:9650/ext/bc/C/proposervm | ||
``` | ||
|
||
**Example Response:** | ||
|
||
```json | ||
{ | ||
"jsonrpc":"2.0", | ||
"result":{ | ||
"block":{ | ||
"SignedBlock":{ | ||
"block":{ | ||
"parentID":"gNms4aTjhR3vLDsTLhNtuWdv6S6xpA6vLjPB53uWSYRxxi3b", | ||
"timestamp":1750694509, | ||
"pChainHeight":0, | ||
"certificate":"MIIFNzCCAx8CCQC687XFxtDRSjANBgkqhkiG9w0BAQsFADB/MQswCQYDVQQGEwJVUzELMAkGA1UECAwCTlkxDzANBgNVBAcMBkl0aGFjYTEQMA4GA1UECgwHQXZhbGFiczEOMAwGA1UECwwFR2Vja28xDDAKBgNVBAMMA2F2YTEiMCAGCSqGSIb3DQEJARYTc3RlcGhlbkBhdmFsYWJzLm9yZzAgFw0xOTA3MDIxNjEyMTlaGA8zMDE5MDcxMDE2MTIxOVowOjELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAk5ZMRAwDgYDVQQKDAdBdmFsYWJzMQwwCgYDVQQDDANhdmEwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDdToR60na6NuR9iSAUMyzPXJNMWVQbLyT5/iZCiJ3BB4YWMBhfxpJWJiWXcM+znDgpJuyCEeh5Dp6ZY3Fe7k6Hht6FmFpDjwnjpQmdkEKUg00G+ElPTp/UsmsPL+JAswPqBZWpMBS3dsXQNunMMtMGlrf5S0l6XX4y7kc/GTxYgveWZ9JtR/m2KNer+wjgBHqJ4rPqnHB30sDYPZg91Cz1Ak8Bb2w2I108zQVgKK6eIqNKXJJ/4pizSZdU4920wMxYBpnfDAchnxei9U/v3QbT7eKUI2fGr+hOWTIWU80+VeOBt8a6P4sS9AQh5/6G8qwmAqO3YQ9dxN82iu/H3+N+GGa/M0r5rEWrzwIuFhwKvyQcpPRBm2yQnBnhL9G5kN6n4OBM0KsgZ3CYlHZSg4eWcNgBt1WCFsQc7vfUFaJnr8QP3pF4V/4Bok7wTO5HN0A1EYEVYuX53NGnrKVe+Fg9+xMOgXPWkUNqdvpI9ZbV3Z0S5866qF3/vBZrhgCrKc5E/vMexBRe8Ki4wKqONVhi9WGUcRHvFEikc+7VrPj0YaG6zVLd+uOAJN81fKOPYo4X4sZrMyPYl3OjGtMhfV4KvCaLEr1duOklqO6cCvGQ8iAlLVy3VJyW5GJ0D0KyiAir4VNdAJKo1ZgiGivJLWulTfjUifCN9o115AiqJxiqwwIDAQABMA0GCSqGSIb3DQEBCwUAA4ICAQCQOdwD7eRIxBvbQHUc+m0TRzEa17BCfck1Y2WwN3TZXDGSkPVE0uujA8SL3qi8/CTLGRqI9U3gRZJf+tJPBF/P021PEmyaFTS4htxcDxTxuZv2jCo9+XhUEyvRWitTmoy1esq3mkotVQHeTmQvwCsQJAhctVA/hRdJwmMPs1B8QxOUI6BqSOBHa9CsXIzVOFv8FqE91PZA2ns30sKQYrrnbH99apfF5WglLUoyPwxf2e3AACh7beEdk45ivvKwi5Jk8nr85KDHYPlqkr0bd9Ehl8xplaNBdMPeRufqBDlztjcLJ3womnrt95gQMeSoLHY3UNsIRjbj43zImu7q9v/DD9ppQpu26aRDRmBNgLZA9GM5XnbZRFi3VxLyqasGcSzaHwz5c7vOBOkOdlqcQzISRvWDxiN1HkAL+hkiQCuMchgORAgMwzPooa8rfWtLIpOXMpwuVGb/8rGNLEPovoCK9z6c+WZ+zkRo4+3TQkOMY66Xht7rAhly3ler+Tyg6a5jXT92WKC/MXBYAy2ZQNoy204kNKevcH7R2cSkxITd3n5EacNy5MAtCNIk7JweLCh9rLrLUBt+i4n44sP+LVhfWHemngA8CoF4n6eQ0pp0ixZTen0j4uN0G2Nf+JeGMlqoObLWdIOdH/pbDppXGoZaKKDd7+bA74Fle5Uh7+1e3A==", | ||
"block":"+QNw+QKYoFe0OHP1nW4P9JOQnoNzUC6qgo8OtNfb6Zm4Vfm4ldiMoB3MTejex116q4W1Z7bM1BrTEkUblIp0E/ChQv1A1JNHlAEAAAAAAAAAAAAAAAAAAAAAAAAAoGhdzXMedsLmpQPfV1mrEbMk8DyPJgkGN61NuyatVSL7oE77qnZEMeujlrntulL1lKZmBHNDJ2GTHJi0nvAEZ7h+oNlbZzgY+kk97sQU4B5hDZfuKHyUIcjv9BArFkfBoYTkuQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEMg+ThwIKkEIRoWXptuFYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIgAAAAAAAAAAKBW6B8XG8xVpv+DReaSwPhuW0jgG5lsrcABYi+142O0IYQ7msoAgICAgKAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPjQ+GYQhTRjC4oAglIIlI25fHzs4knCuYvcAibMTCpXv1L8AYCCCpWgfvDG1UyDlkjqbP4ZHDfvxbqdkRVpXgYYcLYBwc5kfnWgPgZkWcsIU6jWf3t3d1NRWyzmJ1U6TZtRsGrWvfMQK474ZhGFNGMLigCCUgiUjbl8fOziScK5i9wCJsxMKle/UvwBgIIKlqA6HBjup31PCKKeSCRCyi8r61vIVo4naEcOvbauBTgkJKBuIF7y4Cc8SB8uKKYOUEV126BxRghgGIDYeQapjeQbs8CAgA=="}, | ||
"signature":"v8x0g+LFOcLZJaG07tZeLL+uOeKEvoLXfuhsB40aHU9U2MRsZpXWYZpYkTfqvNSo6TyUOUxNg0WLEiWYudafSfDJ5ht0atRtkXEMNHXJdZXRfD7xqox+hG/YojG9toaHogjudSzWTs+GKIvsYQaIcI401U7LFepBeOHauKdBCa4VFCQKCM3a6dyOxtsXz+/8LQgU6QjldnZwDG+jpLvhyE5Tf9fS8oSRv5zjxeVzCAJ8GYo1R62aI9NlNZsMcJwmCr9qBM3Fm8tKZQBsZsnMK+yuSeknWi81FyYHYqe0xkYSFYNZCiXedKkkpmpD0rGm8JrftmTlUvwLGyYFlN9XeVszTBJWJ+ESYG14R5D2kW3LYQ8eEKQk8O+CRM3n0vBjHgJbKNVPiiQAPzeStCCh7rYqiiGifp634yeLfhTfx4TnNs4vrSIOqcLZfpi0Uf06IStrhjp3nVWoDq0oTkngVWeSZj44MW56MaxrGRXpah3VCSTEj/u31G3zY7qjyBhEV0EVd6p5PLOpre9zMB7OyPdWH2CmGH8T7TTS4XVqeVn9WxCk91PQfdkAIt4qLqQB4lFs2ReipIwDDizAst+qXeyCrxj2dyRipaWKnRKHcrRfeCyKGFRWQVjtdVMcwC0gUBcN6VFHqOsrg2T7g9dHIr7mjhZUzzFNYpWZ43lWF/8=" | ||
} | ||
}, | ||
"encoding":"json" | ||
}, | ||
"id":1 | ||
} | ||
``` |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -7,8 +7,10 @@ import ( | |
"context" | ||
"errors" | ||
"fmt" | ||
"net/http" | ||
"time" | ||
|
||
"github.com/gorilla/rpc/v2" | ||
"github.com/prometheus/client_golang/prometheus" | ||
"go.uber.org/zap" | ||
|
||
|
@@ -24,6 +26,7 @@ import ( | |
"github.com/ava-labs/avalanchego/snow/engine/common" | ||
"github.com/ava-labs/avalanchego/snow/engine/snowman/block" | ||
"github.com/ava-labs/avalanchego/utils/constants" | ||
"github.com/ava-labs/avalanchego/utils/json" | ||
"github.com/ava-labs/avalanchego/utils/math" | ||
"github.com/ava-labs/avalanchego/utils/timer/mockable" | ||
"github.com/ava-labs/avalanchego/utils/units" | ||
|
@@ -251,6 +254,25 @@ func (vm *VM) Shutdown(ctx context.Context) error { | |
return vm.ChainVM.Shutdown(ctx) | ||
} | ||
|
||
// overriddes ChainVM.CreateHandlers to expose the proposervm API path | ||
func (vm *VM) CreateHandlers(ctx context.Context) (map[string]http.Handler, error) { | ||
handlers, err := vm.ChainVM.CreateHandlers(ctx) | ||
if err != nil { | ||
return nil, fmt.Errorf("failed to create inner VM handlers: %w", err) | ||
} | ||
|
||
server := rpc.NewServer() | ||
server.RegisterCodec(json.NewCodec(), "application/json") | ||
server.RegisterCodec(json.NewCodec(), "application/json;charset=UTF-8") | ||
err = server.RegisterService(&ProposerAPI{vm}, "proposervm") | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why don't we have these two also similar to the platformVM?
Any thoughts about this? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Added metrics for the proposer vm. Currently, it only contains metrics.APIInterceptor. We will add more metrics when we need later. |
||
if err != nil { | ||
return nil, fmt.Errorf("failed to register proposervm service: %w", err) | ||
} | ||
handlers["/proposervm"] = server | ||
|
||
return handlers, nil | ||
} | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. what about a unit test that invokes this API? |
||
func (vm *VM) SetState(ctx context.Context, newState snow.State) error { | ||
if err := vm.ChainVM.SetState(ctx, newState); err != nil { | ||
return err | ||
|
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.
Can we add unit tests for this file?
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.
Added unit tests.