mirror of
https://github.com/tendermint/tendermint.git
synced 2026-07-31 12:32:54 +00:00
rpc/client: take context as first param (#5347)
Closes #5145 also applies to light/client
This commit is contained in:
+37
-31
@@ -2,6 +2,7 @@ package light
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"time"
|
||||
@@ -151,6 +152,7 @@ type Client struct {
|
||||
//
|
||||
// See all Option(s) for the additional configuration.
|
||||
func NewClient(
|
||||
ctx context.Context,
|
||||
chainID string,
|
||||
trustOptions TrustOptions,
|
||||
primary provider.Provider,
|
||||
@@ -169,14 +171,14 @@ func NewClient(
|
||||
|
||||
if c.latestTrustedBlock != nil {
|
||||
c.logger.Info("Checking trusted light block using options")
|
||||
if err := c.checkTrustedHeaderUsingOptions(trustOptions); err != nil {
|
||||
if err := c.checkTrustedHeaderUsingOptions(ctx, trustOptions); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
if c.latestTrustedBlock == nil || c.latestTrustedBlock.Height < trustOptions.Height {
|
||||
c.logger.Info("Downloading trusted light block using options")
|
||||
if err := c.initializeWithTrustOptions(trustOptions); err != nil {
|
||||
if err := c.initializeWithTrustOptions(ctx, trustOptions); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
@@ -277,11 +279,11 @@ func (c *Client) restoreTrustedLightBlock() error {
|
||||
//
|
||||
// The intuition here is the user is always right. I.e. if she decides to reset
|
||||
// the light client with an older header, there must be a reason for it.
|
||||
func (c *Client) checkTrustedHeaderUsingOptions(options TrustOptions) error {
|
||||
func (c *Client) checkTrustedHeaderUsingOptions(ctx context.Context, options TrustOptions) error {
|
||||
var primaryHash []byte
|
||||
switch {
|
||||
case options.Height > c.latestTrustedBlock.Height:
|
||||
h, err := c.lightBlockFromPrimary(c.latestTrustedBlock.Height)
|
||||
h, err := c.lightBlockFromPrimary(ctx, c.latestTrustedBlock.Height)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -336,9 +338,9 @@ func (c *Client) checkTrustedHeaderUsingOptions(options TrustOptions) error {
|
||||
|
||||
// initializeWithTrustOptions fetches the weakly-trusted light block from
|
||||
// primary provider.
|
||||
func (c *Client) initializeWithTrustOptions(options TrustOptions) error {
|
||||
func (c *Client) initializeWithTrustOptions(ctx context.Context, options TrustOptions) error {
|
||||
// 1) Fetch and verify the light block.
|
||||
l, err := c.lightBlockFromPrimary(options.Height)
|
||||
l, err := c.lightBlockFromPrimary(ctx, options.Height)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -405,7 +407,7 @@ func (c *Client) compareWithLatestHeight(height int64) (int64, error) {
|
||||
// Update attempts to advance the state by downloading the latest light
|
||||
// block and verifying it. It returns a new light block on a successful
|
||||
// update. Otherwise, it returns nil (plus an error, if any).
|
||||
func (c *Client) Update(now time.Time) (*types.LightBlock, error) {
|
||||
func (c *Client) Update(ctx context.Context, now time.Time) (*types.LightBlock, error) {
|
||||
lastTrustedHeight, err := c.LastTrustedHeight()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("can't get last trusted height: %w", err)
|
||||
@@ -416,13 +418,13 @@ func (c *Client) Update(now time.Time) (*types.LightBlock, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
latestBlock, err := c.lightBlockFromPrimary(0)
|
||||
latestBlock, err := c.lightBlockFromPrimary(ctx, 0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if latestBlock.Height > lastTrustedHeight {
|
||||
err = c.verifyLightBlock(latestBlock, now)
|
||||
err = c.verifyLightBlock(ctx, latestBlock, now)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -443,7 +445,7 @@ func (c *Client) Update(now time.Time) (*types.LightBlock, error) {
|
||||
// primary.
|
||||
//
|
||||
// It will replace the primary provider if an error from a request to the provider occurs
|
||||
func (c *Client) VerifyLightBlockAtHeight(height int64, now time.Time) (*types.LightBlock, error) {
|
||||
func (c *Client) VerifyLightBlockAtHeight(ctx context.Context, height int64, now time.Time) (*types.LightBlock, error) {
|
||||
if height <= 0 {
|
||||
return nil, errors.New("negative or zero height")
|
||||
}
|
||||
@@ -457,12 +459,12 @@ func (c *Client) VerifyLightBlockAtHeight(height int64, now time.Time) (*types.L
|
||||
}
|
||||
|
||||
// Request the light block from primary
|
||||
l, err := c.lightBlockFromPrimary(height)
|
||||
l, err := c.lightBlockFromPrimary(ctx, height)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return l, c.verifyLightBlock(l, now)
|
||||
return l, c.verifyLightBlock(ctx, l, now)
|
||||
}
|
||||
|
||||
// VerifyHeader verifies a new header against the trusted state. It returns
|
||||
@@ -493,7 +495,7 @@ func (c *Client) VerifyLightBlockAtHeight(height int64, now time.Time) (*types.L
|
||||
// If, at any moment, a LightBlock is not found by the primary provider as part of
|
||||
// verification then the provider will be replaced by another and the process will
|
||||
// restart.
|
||||
func (c *Client) VerifyHeader(newHeader *types.Header, now time.Time) error {
|
||||
func (c *Client) VerifyHeader(ctx context.Context, newHeader *types.Header, now time.Time) error {
|
||||
if newHeader == nil {
|
||||
return errors.New("nil header")
|
||||
}
|
||||
@@ -514,7 +516,7 @@ func (c *Client) VerifyHeader(newHeader *types.Header, now time.Time) error {
|
||||
}
|
||||
|
||||
// Request the header and the vals.
|
||||
l, err = c.lightBlockFromPrimary(newHeader.Height)
|
||||
l, err = c.lightBlockFromPrimary(ctx, newHeader.Height)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to retrieve light block from primary to verify against: %w", err)
|
||||
}
|
||||
@@ -523,14 +525,14 @@ func (c *Client) VerifyHeader(newHeader *types.Header, now time.Time) error {
|
||||
return fmt.Errorf("light block header %X does not match newHeader %X", l.Hash(), newHeader.Hash())
|
||||
}
|
||||
|
||||
return c.verifyLightBlock(l, now)
|
||||
return c.verifyLightBlock(ctx, l, now)
|
||||
}
|
||||
|
||||
func (c *Client) verifyLightBlock(newLightBlock *types.LightBlock, now time.Time) error {
|
||||
func (c *Client) verifyLightBlock(ctx context.Context, newLightBlock *types.LightBlock, now time.Time) error {
|
||||
c.logger.Info("VerifyHeader", "height", newLightBlock.Height, "hash", hash2str(newLightBlock.Hash()))
|
||||
|
||||
var (
|
||||
verifyFunc func(trusted *types.LightBlock, new *types.LightBlock, now time.Time) error
|
||||
verifyFunc func(ctx context.Context, trusted *types.LightBlock, new *types.LightBlock, now time.Time) error
|
||||
err error
|
||||
)
|
||||
|
||||
@@ -551,7 +553,7 @@ func (c *Client) verifyLightBlock(newLightBlock *types.LightBlock, now time.Time
|
||||
switch {
|
||||
// Verifying forwards
|
||||
case newLightBlock.Height >= c.latestTrustedBlock.Height:
|
||||
err = verifyFunc(c.latestTrustedBlock, newLightBlock, now)
|
||||
err = verifyFunc(ctx, c.latestTrustedBlock, newLightBlock, now)
|
||||
|
||||
// Verifying backwards
|
||||
case newLightBlock.Height < firstBlockHeight:
|
||||
@@ -560,7 +562,7 @@ func (c *Client) verifyLightBlock(newLightBlock *types.LightBlock, now time.Time
|
||||
if err != nil {
|
||||
return fmt.Errorf("can't get first light block: %w", err)
|
||||
}
|
||||
err = c.backwards(firstBlock.Header, newLightBlock.Header)
|
||||
err = c.backwards(ctx, firstBlock.Header, newLightBlock.Header)
|
||||
|
||||
// Verifying between first and last trusted light block
|
||||
default:
|
||||
@@ -569,7 +571,7 @@ func (c *Client) verifyLightBlock(newLightBlock *types.LightBlock, now time.Time
|
||||
if err != nil {
|
||||
return fmt.Errorf("can't get signed header before height %d: %w", newLightBlock.Height, err)
|
||||
}
|
||||
err = verifyFunc(closestBlock, newLightBlock, now)
|
||||
err = verifyFunc(ctx, closestBlock, newLightBlock, now)
|
||||
}
|
||||
if err != nil {
|
||||
c.logger.Error("Can't verify", "err", err)
|
||||
@@ -582,6 +584,7 @@ func (c *Client) verifyLightBlock(newLightBlock *types.LightBlock, now time.Time
|
||||
|
||||
// see VerifyHeader
|
||||
func (c *Client) verifySequential(
|
||||
ctx context.Context,
|
||||
trustedBlock *types.LightBlock,
|
||||
newLightBlock *types.LightBlock,
|
||||
now time.Time) error {
|
||||
@@ -597,7 +600,7 @@ func (c *Client) verifySequential(
|
||||
if height == newLightBlock.Height { // last light block
|
||||
interimBlock = newLightBlock
|
||||
} else { // intermediate light blocks
|
||||
interimBlock, err = c.lightBlockFromPrimary(height)
|
||||
interimBlock, err = c.lightBlockFromPrimary(ctx, height)
|
||||
if err != nil {
|
||||
return ErrVerificationFailed{From: verifiedBlock.Height, To: height, Reason: err}
|
||||
}
|
||||
@@ -633,7 +636,7 @@ func (c *Client) verifySequential(
|
||||
return err
|
||||
}
|
||||
|
||||
replacementBlock, fErr := c.lightBlockFromPrimary(newLightBlock.Height)
|
||||
replacementBlock, fErr := c.lightBlockFromPrimary(ctx, newLightBlock.Height)
|
||||
if fErr != nil {
|
||||
c.logger.Error("Can't fetch light block from primary", "err", fErr)
|
||||
// return original error
|
||||
@@ -672,6 +675,7 @@ func (c *Client) verifySequential(
|
||||
// light client tries again to verify the new light block in the middle, the light
|
||||
// client does not need to ask for all the same light blocks again.
|
||||
func (c *Client) verifySkipping(
|
||||
ctx context.Context,
|
||||
source provider.Provider,
|
||||
trustedBlock *types.LightBlock,
|
||||
newLightBlock *types.LightBlock,
|
||||
@@ -715,7 +719,7 @@ func (c *Client) verifySkipping(
|
||||
if depth == len(blockCache)-1 {
|
||||
pivotHeight := verifiedBlock.Height + (blockCache[depth].Height-verifiedBlock.
|
||||
Height)*verifySkippingNumerator/verifySkippingDenominator
|
||||
interimBlock, providerErr := source.LightBlock(pivotHeight)
|
||||
interimBlock, providerErr := source.LightBlock(ctx, pivotHeight)
|
||||
if providerErr != nil {
|
||||
return nil, ErrVerificationFailed{From: verifiedBlock.Height, To: pivotHeight, Reason: providerErr}
|
||||
}
|
||||
@@ -732,11 +736,12 @@ func (c *Client) verifySkipping(
|
||||
// verifySkippingAgainstPrimary does verifySkipping plus it compares new header with
|
||||
// witnesses and replaces primary if it sends the light client an invalid header
|
||||
func (c *Client) verifySkippingAgainstPrimary(
|
||||
ctx context.Context,
|
||||
trustedBlock *types.LightBlock,
|
||||
newLightBlock *types.LightBlock,
|
||||
now time.Time) error {
|
||||
|
||||
trace, err := c.verifySkipping(c.primary, trustedBlock, newLightBlock, now)
|
||||
trace, err := c.verifySkipping(ctx, c.primary, trustedBlock, newLightBlock, now)
|
||||
|
||||
switch errors.Unwrap(err).(type) {
|
||||
case ErrInvalidHeader:
|
||||
@@ -757,7 +762,7 @@ func (c *Client) verifySkippingAgainstPrimary(
|
||||
return err
|
||||
}
|
||||
|
||||
replacementBlock, fErr := c.lightBlockFromPrimary(newLightBlock.Height)
|
||||
replacementBlock, fErr := c.lightBlockFromPrimary(ctx, newLightBlock.Height)
|
||||
if fErr != nil {
|
||||
c.logger.Error("Can't fetch light block from primary", "err", fErr)
|
||||
// return original error
|
||||
@@ -773,14 +778,14 @@ func (c *Client) verifySkippingAgainstPrimary(
|
||||
}
|
||||
|
||||
// attempt to verify the header again
|
||||
return c.verifySkippingAgainstPrimary(trustedBlock, replacementBlock, now)
|
||||
return c.verifySkippingAgainstPrimary(ctx, trustedBlock, replacementBlock, now)
|
||||
case nil:
|
||||
// Compare header with the witnesses to ensure it's not a fork.
|
||||
// More witnesses we have, more chance to notice one.
|
||||
//
|
||||
// CORRECTNESS ASSUMPTION: there's at least 1 correct full node
|
||||
// (primary or one of the witnesses).
|
||||
if cmpErr := c.detectDivergence(trace, now); cmpErr != nil {
|
||||
if cmpErr := c.detectDivergence(ctx, trace, now); cmpErr != nil {
|
||||
return cmpErr
|
||||
}
|
||||
default:
|
||||
@@ -892,6 +897,7 @@ func (c *Client) updateTrustedLightBlock(l *types.LightBlock) error {
|
||||
// headers before a trusted header. If a sent header is invalid the primary is
|
||||
// replaced with another provider and the operation is repeated.
|
||||
func (c *Client) backwards(
|
||||
ctx context.Context,
|
||||
trustedHeader *types.Header,
|
||||
newHeader *types.Header) error {
|
||||
|
||||
@@ -901,7 +907,7 @@ func (c *Client) backwards(
|
||||
)
|
||||
|
||||
for verifiedHeader.Height > newHeader.Height {
|
||||
interimBlock, err := c.lightBlockFromPrimary(verifiedHeader.Height - 1)
|
||||
interimBlock, err := c.lightBlockFromPrimary(ctx, verifiedHeader.Height-1)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to obtain the header at height #%d: %w", verifiedHeader.Height-1, err)
|
||||
}
|
||||
@@ -960,9 +966,9 @@ func (c *Client) replacePrimaryProvider() error {
|
||||
// lightBlockFromPrimary retrieves the lightBlock from the primary provider
|
||||
// at the specified height. Handles dropout by the primary provider by swapping
|
||||
// with an alternative provider.
|
||||
func (c *Client) lightBlockFromPrimary(height int64) (*types.LightBlock, error) {
|
||||
func (c *Client) lightBlockFromPrimary(ctx context.Context, height int64) (*types.LightBlock, error) {
|
||||
c.providerMutex.Lock()
|
||||
l, err := c.primary.LightBlock(height)
|
||||
l, err := c.primary.LightBlock(ctx, height)
|
||||
c.providerMutex.Unlock()
|
||||
if err != nil {
|
||||
c.logger.Debug("Error on light block request from primary", "error", err)
|
||||
@@ -971,7 +977,7 @@ func (c *Client) lightBlockFromPrimary(height int64) (*types.LightBlock, error)
|
||||
return nil, fmt.Errorf("%v. Tried to replace primary but: %w", err.Error(), replaceErr)
|
||||
}
|
||||
// replace primary and request a light block again
|
||||
return c.lightBlockFromPrimary(height)
|
||||
return c.lightBlockFromPrimary(ctx, height)
|
||||
}
|
||||
return l, err
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package light_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
@@ -22,11 +23,12 @@ import (
|
||||
// Remember that none of these benchmarks account for network latency.
|
||||
var (
|
||||
benchmarkFullNode = mockp.New(genMockNode(chainID, 1000, 100, 1, bTime))
|
||||
genesisBlock, _ = benchmarkFullNode.LightBlock(1)
|
||||
genesisBlock, _ = benchmarkFullNode.LightBlock(context.Background(), 1)
|
||||
)
|
||||
|
||||
func BenchmarkSequence(b *testing.B) {
|
||||
c, err := light.NewClient(
|
||||
context.Background(),
|
||||
chainID,
|
||||
light.TrustOptions{
|
||||
Period: 24 * time.Hour,
|
||||
@@ -45,7 +47,7 @@ func BenchmarkSequence(b *testing.B) {
|
||||
b.ResetTimer()
|
||||
|
||||
for n := 0; n < b.N; n++ {
|
||||
_, err = c.VerifyLightBlockAtHeight(1000, bTime.Add(1000*time.Minute))
|
||||
_, err = c.VerifyLightBlockAtHeight(context.Background(), 1000, bTime.Add(1000*time.Minute))
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
@@ -54,6 +56,7 @@ func BenchmarkSequence(b *testing.B) {
|
||||
|
||||
func BenchmarkBisection(b *testing.B) {
|
||||
c, err := light.NewClient(
|
||||
context.Background(),
|
||||
chainID,
|
||||
light.TrustOptions{
|
||||
Period: 24 * time.Hour,
|
||||
@@ -71,7 +74,7 @@ func BenchmarkBisection(b *testing.B) {
|
||||
b.ResetTimer()
|
||||
|
||||
for n := 0; n < b.N; n++ {
|
||||
_, err = c.VerifyLightBlockAtHeight(1000, bTime.Add(1000*time.Minute))
|
||||
_, err = c.VerifyLightBlockAtHeight(context.Background(), 1000, bTime.Add(1000*time.Minute))
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
@@ -79,8 +82,9 @@ func BenchmarkBisection(b *testing.B) {
|
||||
}
|
||||
|
||||
func BenchmarkBackwards(b *testing.B) {
|
||||
trustedBlock, _ := benchmarkFullNode.LightBlock(0)
|
||||
trustedBlock, _ := benchmarkFullNode.LightBlock(context.Background(), 0)
|
||||
c, err := light.NewClient(
|
||||
context.Background(),
|
||||
chainID,
|
||||
light.TrustOptions{
|
||||
Period: 24 * time.Hour,
|
||||
@@ -98,7 +102,7 @@ func BenchmarkBackwards(b *testing.B) {
|
||||
b.ResetTimer()
|
||||
|
||||
for n := 0; n < b.N; n++ {
|
||||
_, err = c.VerifyLightBlockAtHeight(1, bTime)
|
||||
_, err = c.VerifyLightBlockAtHeight(context.Background(), 1, bTime)
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
|
||||
+47
-25
@@ -1,6 +1,7 @@
|
||||
package light_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"sync"
|
||||
"testing"
|
||||
"time"
|
||||
@@ -23,6 +24,7 @@ const (
|
||||
)
|
||||
|
||||
var (
|
||||
ctx = context.Background()
|
||||
keys = genPrivKeys(4)
|
||||
vals = keys.ToValidators(20, 10)
|
||||
bTime, _ = time.Parse(time.RFC3339, "2006-01-02T15:04:05Z")
|
||||
@@ -111,7 +113,7 @@ func TestValidateTrustOptions(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestMock(t *testing.T) {
|
||||
l, _ := fullNode.LightBlock(3)
|
||||
l, _ := fullNode.LightBlock(ctx, 3)
|
||||
assert.Equal(t, int64(3), l.Height)
|
||||
}
|
||||
|
||||
@@ -216,6 +218,7 @@ func TestClient_SequentialVerification(t *testing.T) {
|
||||
tc := tc
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
c, err := light.NewClient(
|
||||
ctx,
|
||||
chainID,
|
||||
trustOptions,
|
||||
mockp.New(
|
||||
@@ -240,7 +243,7 @@ func TestClient_SequentialVerification(t *testing.T) {
|
||||
|
||||
require.NoError(t, err)
|
||||
|
||||
_, err = c.VerifyLightBlockAtHeight(3, bTime.Add(3*time.Hour))
|
||||
_, err = c.VerifyLightBlockAtHeight(ctx, 3, bTime.Add(3*time.Hour))
|
||||
if tc.verifyErr {
|
||||
assert.Error(t, err)
|
||||
} else {
|
||||
@@ -340,6 +343,7 @@ func TestClient_SkippingVerification(t *testing.T) {
|
||||
tc := tc
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
c, err := light.NewClient(
|
||||
ctx,
|
||||
chainID,
|
||||
trustOptions,
|
||||
mockp.New(
|
||||
@@ -363,7 +367,7 @@ func TestClient_SkippingVerification(t *testing.T) {
|
||||
|
||||
require.NoError(t, err)
|
||||
|
||||
_, err = c.VerifyLightBlockAtHeight(3, bTime.Add(3*time.Hour))
|
||||
_, err = c.VerifyLightBlockAtHeight(ctx, 3, bTime.Add(3*time.Hour))
|
||||
if tc.verifyErr {
|
||||
assert.Error(t, err)
|
||||
} else {
|
||||
@@ -378,9 +382,10 @@ func TestClient_SkippingVerification(t *testing.T) {
|
||||
// the appropriate range
|
||||
func TestClientLargeBisectionVerification(t *testing.T) {
|
||||
veryLargeFullNode := mockp.New(genMockNode(chainID, 100, 3, 0, bTime))
|
||||
trustedLightBlock, err := veryLargeFullNode.LightBlock(5)
|
||||
trustedLightBlock, err := veryLargeFullNode.LightBlock(ctx, 5)
|
||||
require.NoError(t, err)
|
||||
c, err := light.NewClient(
|
||||
ctx,
|
||||
chainID,
|
||||
light.TrustOptions{
|
||||
Period: 4 * time.Hour,
|
||||
@@ -393,15 +398,16 @@ func TestClientLargeBisectionVerification(t *testing.T) {
|
||||
light.SkippingVerification(light.DefaultTrustLevel),
|
||||
)
|
||||
require.NoError(t, err)
|
||||
h, err := c.Update(bTime.Add(100 * time.Minute))
|
||||
h, err := c.Update(ctx, bTime.Add(100*time.Minute))
|
||||
assert.NoError(t, err)
|
||||
h2, err := veryLargeFullNode.LightBlock(100)
|
||||
h2, err := veryLargeFullNode.LightBlock(ctx, 100)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, h, h2)
|
||||
}
|
||||
|
||||
func TestClientBisectionBetweenTrustedHeaders(t *testing.T) {
|
||||
c, err := light.NewClient(
|
||||
ctx,
|
||||
chainID,
|
||||
light.TrustOptions{
|
||||
Period: 4 * time.Hour,
|
||||
@@ -415,7 +421,7 @@ func TestClientBisectionBetweenTrustedHeaders(t *testing.T) {
|
||||
)
|
||||
require.NoError(t, err)
|
||||
|
||||
_, err = c.VerifyLightBlockAtHeight(3, bTime.Add(2*time.Hour))
|
||||
_, err = c.VerifyLightBlockAtHeight(ctx, 3, bTime.Add(2*time.Hour))
|
||||
require.NoError(t, err)
|
||||
|
||||
// confirm that the client already doesn't have the light block
|
||||
@@ -423,12 +429,13 @@ func TestClientBisectionBetweenTrustedHeaders(t *testing.T) {
|
||||
require.Error(t, err)
|
||||
|
||||
// verify using bisection the light block between the two trusted light blocks
|
||||
_, err = c.VerifyLightBlockAtHeight(2, bTime.Add(1*time.Hour))
|
||||
_, err = c.VerifyLightBlockAtHeight(ctx, 2, bTime.Add(1*time.Hour))
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
|
||||
func TestClient_Cleanup(t *testing.T) {
|
||||
c, err := light.NewClient(
|
||||
ctx,
|
||||
chainID,
|
||||
trustOptions,
|
||||
fullNode,
|
||||
@@ -458,6 +465,7 @@ func TestClientRestoresTrustedHeaderAfterStartup1(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
|
||||
c, err := light.NewClient(
|
||||
ctx,
|
||||
chainID,
|
||||
trustOptions,
|
||||
fullNode,
|
||||
@@ -494,6 +502,7 @@ func TestClientRestoresTrustedHeaderAfterStartup1(t *testing.T) {
|
||||
)
|
||||
|
||||
c, err := light.NewClient(
|
||||
ctx,
|
||||
chainID,
|
||||
light.TrustOptions{
|
||||
Period: 4 * time.Hour,
|
||||
@@ -525,6 +534,7 @@ func TestClientRestoresTrustedHeaderAfterStartup2(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
|
||||
c, err := light.NewClient(
|
||||
ctx,
|
||||
chainID,
|
||||
light.TrustOptions{
|
||||
Period: 4 * time.Hour,
|
||||
@@ -570,6 +580,7 @@ func TestClientRestoresTrustedHeaderAfterStartup2(t *testing.T) {
|
||||
)
|
||||
|
||||
c, err := light.NewClient(
|
||||
ctx,
|
||||
chainID,
|
||||
light.TrustOptions{
|
||||
Period: 4 * time.Hour,
|
||||
@@ -603,6 +614,7 @@ func TestClientRestoresTrustedHeaderAfterStartup3(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
|
||||
c, err := light.NewClient(
|
||||
ctx,
|
||||
chainID,
|
||||
trustOptions,
|
||||
fullNode,
|
||||
@@ -657,6 +669,7 @@ func TestClientRestoresTrustedHeaderAfterStartup3(t *testing.T) {
|
||||
)
|
||||
|
||||
c, err := light.NewClient(
|
||||
ctx,
|
||||
chainID,
|
||||
light.TrustOptions{
|
||||
Period: 4 * time.Hour,
|
||||
@@ -686,6 +699,7 @@ func TestClientRestoresTrustedHeaderAfterStartup3(t *testing.T) {
|
||||
|
||||
func TestClient_Update(t *testing.T) {
|
||||
c, err := light.NewClient(
|
||||
ctx,
|
||||
chainID,
|
||||
trustOptions,
|
||||
fullNode,
|
||||
@@ -696,7 +710,7 @@ func TestClient_Update(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
|
||||
// should result in downloading & verifying header #3
|
||||
l, err := c.Update(bTime.Add(2 * time.Hour))
|
||||
l, err := c.Update(ctx, bTime.Add(2*time.Hour))
|
||||
assert.NoError(t, err)
|
||||
if assert.NotNil(t, l) {
|
||||
assert.EqualValues(t, 3, l.Height)
|
||||
@@ -706,6 +720,7 @@ func TestClient_Update(t *testing.T) {
|
||||
|
||||
func TestClient_Concurrency(t *testing.T) {
|
||||
c, err := light.NewClient(
|
||||
ctx,
|
||||
chainID,
|
||||
trustOptions,
|
||||
fullNode,
|
||||
@@ -715,7 +730,7 @@ func TestClient_Concurrency(t *testing.T) {
|
||||
)
|
||||
require.NoError(t, err)
|
||||
|
||||
_, err = c.VerifyLightBlockAtHeight(2, bTime.Add(2*time.Hour))
|
||||
_, err = c.VerifyLightBlockAtHeight(ctx, 2, bTime.Add(2*time.Hour))
|
||||
require.NoError(t, err)
|
||||
|
||||
var wg sync.WaitGroup
|
||||
@@ -746,6 +761,7 @@ func TestClient_Concurrency(t *testing.T) {
|
||||
|
||||
func TestClientReplacesPrimaryWithWitnessIfPrimaryIsUnavailable(t *testing.T) {
|
||||
c, err := light.NewClient(
|
||||
ctx,
|
||||
chainID,
|
||||
trustOptions,
|
||||
deadNode,
|
||||
@@ -756,7 +772,7 @@ func TestClientReplacesPrimaryWithWitnessIfPrimaryIsUnavailable(t *testing.T) {
|
||||
)
|
||||
|
||||
require.NoError(t, err)
|
||||
_, err = c.Update(bTime.Add(2 * time.Hour))
|
||||
_, err = c.Update(ctx, bTime.Add(2*time.Hour))
|
||||
require.NoError(t, err)
|
||||
|
||||
assert.NotEqual(t, c.Primary(), deadNode)
|
||||
@@ -765,8 +781,9 @@ func TestClientReplacesPrimaryWithWitnessIfPrimaryIsUnavailable(t *testing.T) {
|
||||
|
||||
func TestClient_BackwardsVerification(t *testing.T) {
|
||||
{
|
||||
trustHeader, _ := largeFullNode.LightBlock(6)
|
||||
trustHeader, _ := largeFullNode.LightBlock(ctx, 6)
|
||||
c, err := light.NewClient(
|
||||
ctx,
|
||||
chainID,
|
||||
light.TrustOptions{
|
||||
Period: 4 * time.Minute,
|
||||
@@ -781,28 +798,28 @@ func TestClient_BackwardsVerification(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
|
||||
// 1) verify before the trusted header using backwards => expect no error
|
||||
h, err := c.VerifyLightBlockAtHeight(5, bTime.Add(6*time.Minute))
|
||||
h, err := c.VerifyLightBlockAtHeight(ctx, 5, bTime.Add(6*time.Minute))
|
||||
require.NoError(t, err)
|
||||
if assert.NotNil(t, h) {
|
||||
assert.EqualValues(t, 5, h.Height)
|
||||
}
|
||||
|
||||
// 2) untrusted header is expired but trusted header is not => expect no error
|
||||
h, err = c.VerifyLightBlockAtHeight(3, bTime.Add(8*time.Minute))
|
||||
h, err = c.VerifyLightBlockAtHeight(ctx, 3, bTime.Add(8*time.Minute))
|
||||
assert.NoError(t, err)
|
||||
assert.NotNil(t, h)
|
||||
|
||||
// 3) already stored headers should return the header without error
|
||||
h, err = c.VerifyLightBlockAtHeight(5, bTime.Add(6*time.Minute))
|
||||
h, err = c.VerifyLightBlockAtHeight(ctx, 5, bTime.Add(6*time.Minute))
|
||||
assert.NoError(t, err)
|
||||
assert.NotNil(t, h)
|
||||
|
||||
// 4a) First verify latest header
|
||||
_, err = c.VerifyLightBlockAtHeight(9, bTime.Add(9*time.Minute))
|
||||
_, err = c.VerifyLightBlockAtHeight(ctx, 9, bTime.Add(9*time.Minute))
|
||||
require.NoError(t, err)
|
||||
|
||||
// 4b) Verify backwards using bisection => expect no error
|
||||
_, err = c.VerifyLightBlockAtHeight(7, bTime.Add(9*time.Minute))
|
||||
_, err = c.VerifyLightBlockAtHeight(ctx, 7, bTime.Add(9*time.Minute))
|
||||
assert.NoError(t, err)
|
||||
// shouldn't have verified this header in the process
|
||||
_, err = c.TrustedLightBlock(8)
|
||||
@@ -810,7 +827,7 @@ func TestClient_BackwardsVerification(t *testing.T) {
|
||||
|
||||
// 5) Try bisection method, but closest header (at 7) has expired
|
||||
// so expect error
|
||||
_, err = c.VerifyLightBlockAtHeight(8, bTime.Add(12*time.Minute))
|
||||
_, err = c.VerifyLightBlockAtHeight(ctx, 8, bTime.Add(12*time.Minute))
|
||||
assert.Error(t, err)
|
||||
|
||||
}
|
||||
@@ -848,6 +865,7 @@ func TestClient_BackwardsVerification(t *testing.T) {
|
||||
|
||||
for idx, tc := range testCases {
|
||||
c, err := light.NewClient(
|
||||
ctx,
|
||||
chainID,
|
||||
light.TrustOptions{
|
||||
Period: 1 * time.Hour,
|
||||
@@ -861,7 +879,7 @@ func TestClient_BackwardsVerification(t *testing.T) {
|
||||
)
|
||||
require.NoError(t, err, idx)
|
||||
|
||||
_, err = c.VerifyLightBlockAtHeight(2, bTime.Add(1*time.Hour).Add(1*time.Second))
|
||||
_, err = c.VerifyLightBlockAtHeight(ctx, 2, bTime.Add(1*time.Hour).Add(1*time.Second))
|
||||
assert.Error(t, err, idx)
|
||||
}
|
||||
}
|
||||
@@ -917,10 +935,11 @@ func TestClientRemovesWitnessIfItSendsUsIncorrectHeader(t *testing.T) {
|
||||
},
|
||||
)
|
||||
|
||||
lb1, _ := badProvider1.LightBlock(2)
|
||||
lb1, _ := badProvider1.LightBlock(ctx, 2)
|
||||
require.NotEqual(t, lb1.Hash(), l1.Hash())
|
||||
|
||||
c, err := light.NewClient(
|
||||
ctx,
|
||||
chainID,
|
||||
trustOptions,
|
||||
fullNode,
|
||||
@@ -934,14 +953,14 @@ func TestClientRemovesWitnessIfItSendsUsIncorrectHeader(t *testing.T) {
|
||||
assert.EqualValues(t, 2, len(c.Witnesses()))
|
||||
|
||||
// witness behaves incorrectly -> removed from list, no error
|
||||
l, err := c.VerifyLightBlockAtHeight(2, bTime.Add(2*time.Hour))
|
||||
l, err := c.VerifyLightBlockAtHeight(ctx, 2, bTime.Add(2*time.Hour))
|
||||
assert.NoError(t, err)
|
||||
assert.EqualValues(t, 1, len(c.Witnesses()))
|
||||
// light block should still be verified
|
||||
assert.EqualValues(t, 2, l.Height)
|
||||
|
||||
// remaining witnesses don't have light block -> error
|
||||
_, err = c.VerifyLightBlockAtHeight(3, bTime.Add(2*time.Hour))
|
||||
_, err = c.VerifyLightBlockAtHeight(ctx, 3, bTime.Add(2*time.Hour))
|
||||
if assert.Error(t, err) {
|
||||
assert.Equal(t, light.ErrFailedHeaderCrossReferencing, err)
|
||||
}
|
||||
@@ -970,6 +989,7 @@ func TestClient_TrustedValidatorSet(t *testing.T) {
|
||||
)
|
||||
|
||||
c, err := light.NewClient(
|
||||
ctx,
|
||||
chainID,
|
||||
trustOptions,
|
||||
fullNode,
|
||||
@@ -980,13 +1000,14 @@ func TestClient_TrustedValidatorSet(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, 2, len(c.Witnesses()))
|
||||
|
||||
_, err = c.VerifyLightBlockAtHeight(2, bTime.Add(2*time.Hour).Add(1*time.Second))
|
||||
_, err = c.VerifyLightBlockAtHeight(ctx, 2, bTime.Add(2*time.Hour).Add(1*time.Second))
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, 1, len(c.Witnesses()))
|
||||
}
|
||||
|
||||
func TestClientPrunesHeadersAndValidatorSets(t *testing.T) {
|
||||
c, err := light.NewClient(
|
||||
ctx,
|
||||
chainID,
|
||||
trustOptions,
|
||||
fullNode,
|
||||
@@ -999,7 +1020,7 @@ func TestClientPrunesHeadersAndValidatorSets(t *testing.T) {
|
||||
_, err = c.TrustedLightBlock(1)
|
||||
require.NoError(t, err)
|
||||
|
||||
h, err := c.Update(bTime.Add(2 * time.Hour))
|
||||
h, err := c.Update(ctx, bTime.Add(2*time.Hour))
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, int64(3), h.Height)
|
||||
|
||||
@@ -1059,6 +1080,7 @@ func TestClientEnsureValidHeadersAndValSets(t *testing.T) {
|
||||
tc.vals,
|
||||
)
|
||||
c, err := light.NewClient(
|
||||
ctx,
|
||||
chainID,
|
||||
trustOptions,
|
||||
badNode,
|
||||
@@ -1068,7 +1090,7 @@ func TestClientEnsureValidHeadersAndValSets(t *testing.T) {
|
||||
)
|
||||
require.NoError(t, err)
|
||||
|
||||
_, err = c.VerifyLightBlockAtHeight(3, bTime.Add(2*time.Hour))
|
||||
_, err = c.VerifyLightBlockAtHeight(ctx, 3, bTime.Add(2*time.Hour))
|
||||
if tc.err {
|
||||
assert.Error(t, err)
|
||||
} else {
|
||||
|
||||
+26
-14
@@ -2,6 +2,7 @@ package light
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"time"
|
||||
@@ -25,7 +26,7 @@ import (
|
||||
//
|
||||
// If there are no conflictinge headers, the light client deems the verified target header
|
||||
// trusted and saves it to the trusted store.
|
||||
func (c *Client) detectDivergence(primaryTrace []*types.LightBlock, now time.Time) error {
|
||||
func (c *Client) detectDivergence(ctx context.Context, primaryTrace []*types.LightBlock, now time.Time) error {
|
||||
if primaryTrace == nil || len(primaryTrace) < 2 {
|
||||
return errors.New("nil or single block primary trace")
|
||||
}
|
||||
@@ -48,7 +49,7 @@ func (c *Client) detectDivergence(primaryTrace []*types.LightBlock, now time.Tim
|
||||
// and compare it with the header from the primary
|
||||
errc := make(chan error, len(c.witnesses))
|
||||
for i, witness := range c.witnesses {
|
||||
go c.compareNewHeaderWithWitness(errc, lastVerifiedHeader, witness, i)
|
||||
go c.compareNewHeaderWithWitness(ctx, errc, lastVerifiedHeader, witness, i)
|
||||
}
|
||||
|
||||
// handle errors from the header comparisons as they come in
|
||||
@@ -66,8 +67,13 @@ func (c *Client) detectDivergence(primaryTrace []*types.LightBlock, now time.Tim
|
||||
// We combine these actions together, verifying the witnesses headers and outputting the trace
|
||||
// which captures the bifurcation point and if successful provides the information to create
|
||||
supportingWitness := c.witnesses[e.WitnessIndex]
|
||||
witnessTrace, primaryBlock, err := c.examineConflictingHeaderAgainstTrace(primaryTrace, e.Block.SignedHeader,
|
||||
supportingWitness, now)
|
||||
witnessTrace, primaryBlock, err := c.examineConflictingHeaderAgainstTrace(
|
||||
ctx,
|
||||
primaryTrace,
|
||||
e.Block.SignedHeader,
|
||||
supportingWitness,
|
||||
now,
|
||||
)
|
||||
if err != nil {
|
||||
c.logger.Info("Error validating witness's divergent header", "witness", supportingWitness, "err", err)
|
||||
witnessesToRemove = append(witnessesToRemove, e.WitnessIndex)
|
||||
@@ -90,13 +96,18 @@ func (c *Client) detectDivergence(primaryTrace []*types.LightBlock, now time.Tim
|
||||
}
|
||||
c.logger.Error("Attack detected. Sending evidence againt primary by witness", "ev", ev,
|
||||
"primary", c.primary, "witness", supportingWitness)
|
||||
c.sendEvidence(ev, supportingWitness)
|
||||
c.sendEvidence(ctx, ev, supportingWitness)
|
||||
|
||||
// This may not be valid because the witness itself is at fault. So now we reverse it, examining the
|
||||
// trace provided by the witness and holding the primary as the source of truth. Note: primary may not
|
||||
// respond but this is okay as we will halt anyway.
|
||||
primaryTrace, witnessBlock, err := c.examineConflictingHeaderAgainstTrace(witnessTrace, primaryBlock.SignedHeader,
|
||||
c.primary, now)
|
||||
primaryTrace, witnessBlock, err := c.examineConflictingHeaderAgainstTrace(
|
||||
ctx,
|
||||
witnessTrace,
|
||||
primaryBlock.SignedHeader,
|
||||
c.primary,
|
||||
now,
|
||||
)
|
||||
if err != nil {
|
||||
c.logger.Info("Error validating primary's divergent header", "primary", c.primary, "err", err)
|
||||
continue
|
||||
@@ -117,7 +128,7 @@ func (c *Client) detectDivergence(primaryTrace []*types.LightBlock, now time.Tim
|
||||
}
|
||||
c.logger.Error("Sending evidence against witness by primary", "ev", ev,
|
||||
"primary", c.primary, "witness", supportingWitness)
|
||||
c.sendEvidence(ev, c.primary)
|
||||
c.sendEvidence(ctx, ev, c.primary)
|
||||
// We return the error and don't process anymore witnesses
|
||||
return e
|
||||
|
||||
@@ -154,10 +165,10 @@ func (c *Client) detectDivergence(primaryTrace []*types.LightBlock, now time.Tim
|
||||
// 2: errBadWitness -> the witness has either not responded, doesn't have the header or has given us an invalid one
|
||||
// Note: In the case of an invalid header we remove the witness
|
||||
// 3: nil -> the hashes of the two headers match
|
||||
func (c *Client) compareNewHeaderWithWitness(errc chan error, h *types.SignedHeader,
|
||||
func (c *Client) compareNewHeaderWithWitness(ctx context.Context, errc chan error, h *types.SignedHeader,
|
||||
witness provider.Provider, witnessIndex int) {
|
||||
|
||||
lightBlock, err := witness.LightBlock(h.Height)
|
||||
lightBlock, err := witness.LightBlock(ctx, h.Height)
|
||||
if err != nil {
|
||||
errc <- errBadWitness{Reason: err, WitnessIndex: witnessIndex}
|
||||
return
|
||||
@@ -172,8 +183,8 @@ func (c *Client) compareNewHeaderWithWitness(errc chan error, h *types.SignedHea
|
||||
}
|
||||
|
||||
// sendEvidence sends evidence to a provider on a best effort basis.
|
||||
func (c *Client) sendEvidence(ev *types.LightClientAttackEvidence, receiver provider.Provider) {
|
||||
err := receiver.ReportEvidence(ev)
|
||||
func (c *Client) sendEvidence(ctx context.Context, ev *types.LightClientAttackEvidence, receiver provider.Provider) {
|
||||
err := receiver.ReportEvidence(ctx, ev)
|
||||
if err != nil {
|
||||
c.logger.Error("Failed to report evidence to provider", "ev", ev, "provider", receiver)
|
||||
}
|
||||
@@ -188,6 +199,7 @@ func (c *Client) sendEvidence(ev *types.LightClientAttackEvidence, receiver prov
|
||||
// 2. The source stops responding, doesn't have the block or sends an invalid header in which case we
|
||||
// return the error and remove the witness
|
||||
func (c *Client) examineConflictingHeaderAgainstTrace(
|
||||
ctx context.Context,
|
||||
trace []*types.LightBlock,
|
||||
divergentHeader *types.SignedHeader,
|
||||
source provider.Provider, now time.Time) ([]*types.LightBlock, *types.LightBlock, error) {
|
||||
@@ -197,7 +209,7 @@ func (c *Client) examineConflictingHeaderAgainstTrace(
|
||||
for idx, traceBlock := range trace {
|
||||
// The first block in the trace MUST be the same to the light block that the source produces
|
||||
// else we cannot continue with verification.
|
||||
sourceBlock, err := source.LightBlock(traceBlock.Height)
|
||||
sourceBlock, err := source.LightBlock(ctx, traceBlock.Height)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
@@ -213,7 +225,7 @@ func (c *Client) examineConflictingHeaderAgainstTrace(
|
||||
|
||||
// we check that the source provider can verify a block at the same height of the
|
||||
// intermediate height
|
||||
trace, err := c.verifySkipping(source, previouslyVerifiedBlock, sourceBlock, now)
|
||||
trace, err := c.verifySkipping(ctx, source, previouslyVerifiedBlock, sourceBlock, now)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("verifySkipping of conflicting header failed: %w", err)
|
||||
}
|
||||
|
||||
@@ -45,6 +45,7 @@ func TestLightClientAttackEvidence_Lunatic(t *testing.T) {
|
||||
primary := mockp.New(chainID, primaryHeaders, primaryValidators)
|
||||
|
||||
c, err := light.NewClient(
|
||||
ctx,
|
||||
chainID,
|
||||
light.TrustOptions{
|
||||
Period: 4 * time.Hour,
|
||||
@@ -60,7 +61,7 @@ func TestLightClientAttackEvidence_Lunatic(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
|
||||
// Check verification returns an error.
|
||||
_, err = c.VerifyLightBlockAtHeight(10, bTime.Add(1*time.Hour))
|
||||
_, err = c.VerifyLightBlockAtHeight(ctx, 10, bTime.Add(1*time.Hour))
|
||||
if assert.Error(t, err) {
|
||||
assert.Contains(t, err.Error(), "does not match primary")
|
||||
}
|
||||
@@ -118,6 +119,7 @@ func TestLightClientAttackEvidence_Equivocation(t *testing.T) {
|
||||
primary := mockp.New(chainID, primaryHeaders, primaryValidators)
|
||||
|
||||
c, err := light.NewClient(
|
||||
ctx,
|
||||
chainID,
|
||||
light.TrustOptions{
|
||||
Period: 4 * time.Hour,
|
||||
@@ -133,7 +135,7 @@ func TestLightClientAttackEvidence_Equivocation(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
|
||||
// Check verification returns an error.
|
||||
_, err = c.VerifyLightBlockAtHeight(10, bTime.Add(1*time.Hour))
|
||||
_, err = c.VerifyLightBlockAtHeight(ctx, 10, bTime.Add(1*time.Hour))
|
||||
if assert.Error(t, err) {
|
||||
assert.Contains(t, err.Error(), "does not match primary")
|
||||
}
|
||||
@@ -162,11 +164,12 @@ func TestLightClientAttackEvidence_Equivocation(t *testing.T) {
|
||||
|
||||
func TestClientDivergentTraces(t *testing.T) {
|
||||
primary := mockp.New(genMockNode(chainID, 10, 5, 2, bTime))
|
||||
firstBlock, err := primary.LightBlock(1)
|
||||
firstBlock, err := primary.LightBlock(ctx, 1)
|
||||
require.NoError(t, err)
|
||||
witness := mockp.New(genMockNode(chainID, 10, 5, 2, bTime))
|
||||
|
||||
c, err := light.NewClient(
|
||||
ctx,
|
||||
chainID,
|
||||
light.TrustOptions{
|
||||
Height: 1,
|
||||
@@ -183,7 +186,7 @@ func TestClientDivergentTraces(t *testing.T) {
|
||||
|
||||
// 1. Different nodes therefore a divergent header is produced but the
|
||||
// light client can't verify it because it has a different trusted header.
|
||||
_, err = c.VerifyLightBlockAtHeight(10, bTime.Add(1*time.Hour))
|
||||
_, err = c.VerifyLightBlockAtHeight(ctx, 10, bTime.Add(1*time.Hour))
|
||||
assert.Error(t, err)
|
||||
assert.Equal(t, 0, len(c.Witnesses()))
|
||||
|
||||
@@ -191,6 +194,7 @@ func TestClientDivergentTraces(t *testing.T) {
|
||||
// verification should be successful and all the witnesses should remain
|
||||
|
||||
c, err = light.NewClient(
|
||||
ctx,
|
||||
chainID,
|
||||
light.TrustOptions{
|
||||
Height: 1,
|
||||
@@ -204,7 +208,7 @@ func TestClientDivergentTraces(t *testing.T) {
|
||||
light.MaxRetryAttempts(1),
|
||||
)
|
||||
require.NoError(t, err)
|
||||
_, err = c.VerifyLightBlockAtHeight(10, bTime.Add(1*time.Hour))
|
||||
_, err = c.VerifyLightBlockAtHeight(ctx, 10, bTime.Add(1*time.Hour))
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, 3, len(c.Witnesses()))
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package light_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
stdlog "log"
|
||||
@@ -40,7 +41,7 @@ func ExampleClient_Update() {
|
||||
stdlog.Fatal(err)
|
||||
}
|
||||
|
||||
block, err := primary.LightBlock(2)
|
||||
block, err := primary.LightBlock(context.Background(), 2)
|
||||
if err != nil {
|
||||
stdlog.Fatal(err)
|
||||
}
|
||||
@@ -51,6 +52,7 @@ func ExampleClient_Update() {
|
||||
}
|
||||
|
||||
c, err := light.NewClient(
|
||||
context.Background(),
|
||||
chainID,
|
||||
light.TrustOptions{
|
||||
Period: 504 * time.Hour, // 21 days
|
||||
@@ -77,7 +79,7 @@ func ExampleClient_Update() {
|
||||
// monotonic component (see types/time/time.go) b) single instance is being
|
||||
// run.
|
||||
// https://github.com/tendermint/tendermint/issues/4489
|
||||
h, err := c.Update(time.Now().Add(30 * time.Minute))
|
||||
h, err := c.Update(context.Background(), time.Now().Add(30*time.Minute))
|
||||
if err != nil {
|
||||
stdlog.Fatal(err)
|
||||
}
|
||||
@@ -111,7 +113,7 @@ func ExampleClient_VerifyLightBlockAtHeight() {
|
||||
stdlog.Fatal(err)
|
||||
}
|
||||
|
||||
block, err := primary.LightBlock(2)
|
||||
block, err := primary.LightBlock(context.Background(), 2)
|
||||
if err != nil {
|
||||
stdlog.Fatal(err)
|
||||
}
|
||||
@@ -122,6 +124,7 @@ func ExampleClient_VerifyLightBlockAtHeight() {
|
||||
}
|
||||
|
||||
c, err := light.NewClient(
|
||||
context.Background(),
|
||||
chainID,
|
||||
light.TrustOptions{
|
||||
Period: 504 * time.Hour, // 21 days
|
||||
@@ -142,7 +145,7 @@ func ExampleClient_VerifyLightBlockAtHeight() {
|
||||
}
|
||||
}()
|
||||
|
||||
_, err = c.VerifyLightBlockAtHeight(3, time.Now())
|
||||
_, err = c.VerifyLightBlockAtHeight(context.Background(), 3, time.Now())
|
||||
if err != nil {
|
||||
stdlog.Fatal(err)
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package http
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"regexp"
|
||||
@@ -61,18 +62,18 @@ func (p *http) String() string {
|
||||
|
||||
// LightBlock fetches a LightBlock at the given height and checks the
|
||||
// chainID matches.
|
||||
func (p *http) LightBlock(height int64) (*types.LightBlock, error) {
|
||||
func (p *http) LightBlock(ctx context.Context, height int64) (*types.LightBlock, error) {
|
||||
h, err := validateHeight(height)
|
||||
if err != nil {
|
||||
return nil, provider.ErrBadLightBlock{Reason: err}
|
||||
}
|
||||
|
||||
sh, err := p.signedHeader(h)
|
||||
sh, err := p.signedHeader(ctx, h)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
vs, err := p.validatorSet(h)
|
||||
vs, err := p.validatorSet(ctx, h)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -91,12 +92,12 @@ func (p *http) LightBlock(height int64) (*types.LightBlock, error) {
|
||||
}
|
||||
|
||||
// ReportEvidence calls `/broadcast_evidence` endpoint.
|
||||
func (p *http) ReportEvidence(ev types.Evidence) error {
|
||||
_, err := p.client.BroadcastEvidence(ev)
|
||||
func (p *http) ReportEvidence(ctx context.Context, ev types.Evidence) error {
|
||||
_, err := p.client.BroadcastEvidence(ctx, ev)
|
||||
return err
|
||||
}
|
||||
|
||||
func (p *http) validatorSet(height *int64) (*types.ValidatorSet, error) {
|
||||
func (p *http) validatorSet(ctx context.Context, height *int64) (*types.ValidatorSet, error) {
|
||||
var (
|
||||
maxPerPage = 100
|
||||
vals = []*types.Validator{}
|
||||
@@ -105,7 +106,7 @@ func (p *http) validatorSet(height *int64) (*types.ValidatorSet, error) {
|
||||
|
||||
for len(vals)%maxPerPage == 0 {
|
||||
for attempt := 1; attempt <= maxRetryAttempts; attempt++ {
|
||||
res, err := p.client.Validators(height, &page, &maxPerPage)
|
||||
res, err := p.client.Validators(ctx, height, &page, &maxPerPage)
|
||||
if err != nil {
|
||||
// TODO: standardize errors on the RPC side
|
||||
if regexpMissingHeight.MatchString(err.Error()) {
|
||||
@@ -138,9 +139,9 @@ func (p *http) validatorSet(height *int64) (*types.ValidatorSet, error) {
|
||||
return valSet, nil
|
||||
}
|
||||
|
||||
func (p *http) signedHeader(height *int64) (*types.SignedHeader, error) {
|
||||
func (p *http) signedHeader(ctx context.Context, height *int64) (*types.SignedHeader, error) {
|
||||
for attempt := 1; attempt <= maxRetryAttempts; attempt++ {
|
||||
commit, err := p.client.Commit(height)
|
||||
commit, err := p.client.Commit(ctx, height)
|
||||
if err != nil {
|
||||
// TODO: standardize errors on the RPC side
|
||||
if regexpMissingHeight.MatchString(err.Error()) {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package http_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
"testing"
|
||||
@@ -65,7 +66,7 @@ func TestProvider(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
|
||||
// let's get the highest block
|
||||
sh, err := p.LightBlock(0)
|
||||
sh, err := p.LightBlock(context.Background(), 0)
|
||||
require.NoError(t, err)
|
||||
assert.True(t, sh.Height < 1000)
|
||||
|
||||
@@ -74,16 +75,16 @@ func TestProvider(t *testing.T) {
|
||||
|
||||
// historical queries now work :)
|
||||
lower := sh.Height - 3
|
||||
sh, err = p.LightBlock(lower)
|
||||
sh, err = p.LightBlock(context.Background(), lower)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, lower, sh.Height)
|
||||
|
||||
// fetching missing heights (both future and pruned) should return appropriate errors
|
||||
_, err = p.LightBlock(1000)
|
||||
_, err = p.LightBlock(context.Background(), 1000)
|
||||
require.Error(t, err)
|
||||
assert.Equal(t, provider.ErrLightBlockNotFound, err)
|
||||
|
||||
_, err = p.LightBlock(1)
|
||||
_, err = p.LightBlock(context.Background(), 1)
|
||||
require.Error(t, err)
|
||||
assert.Equal(t, provider.ErrLightBlockNotFound, err)
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package mock
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
|
||||
"github.com/tendermint/tendermint/light/provider"
|
||||
@@ -22,10 +23,10 @@ func (p *deadMock) ChainID() string { return p.chainID }
|
||||
|
||||
func (p *deadMock) String() string { return "deadMock" }
|
||||
|
||||
func (p *deadMock) LightBlock(height int64) (*types.LightBlock, error) {
|
||||
func (p *deadMock) LightBlock(_ context.Context, height int64) (*types.LightBlock, error) {
|
||||
return nil, errNoResp
|
||||
}
|
||||
|
||||
func (p *deadMock) ReportEvidence(ev types.Evidence) error {
|
||||
func (p *deadMock) ReportEvidence(_ context.Context, ev types.Evidence) error {
|
||||
return errNoResp
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package mock
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
@@ -48,7 +49,7 @@ func (p *Mock) String() string {
|
||||
return fmt.Sprintf("Mock{headers: %s, vals: %v}", headers.String(), vals.String())
|
||||
}
|
||||
|
||||
func (p *Mock) LightBlock(height int64) (*types.LightBlock, error) {
|
||||
func (p *Mock) LightBlock(_ context.Context, height int64) (*types.LightBlock, error) {
|
||||
var lb *types.LightBlock
|
||||
if height == 0 && len(p.headers) > 0 {
|
||||
sh := p.headers[int64(len(p.headers))]
|
||||
@@ -79,7 +80,7 @@ func (p *Mock) LightBlock(height int64) (*types.LightBlock, error) {
|
||||
return lb, nil
|
||||
}
|
||||
|
||||
func (p *Mock) ReportEvidence(ev types.Evidence) error {
|
||||
func (p *Mock) ReportEvidence(_ context.Context, ev types.Evidence) error {
|
||||
p.evidenceToReport[string(ev.Hash())] = ev
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
package provider
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/tendermint/tendermint/types"
|
||||
)
|
||||
|
||||
@@ -20,8 +22,8 @@ type Provider interface {
|
||||
// issues, an error will be returned.
|
||||
// If there's no LightBlock for the given height, ErrLightBlockNotFound
|
||||
// error is returned.
|
||||
LightBlock(height int64) (*types.LightBlock, error)
|
||||
LightBlock(ctx context.Context, height int64) (*types.LightBlock, error)
|
||||
|
||||
// ReportEvidence reports an evidence of misbehavior.
|
||||
ReportEvidence(ev types.Evidence) error
|
||||
ReportEvidence(context.Context, types.Evidence) error
|
||||
}
|
||||
|
||||
+23
-23
@@ -53,7 +53,7 @@ type rpcHealthFunc func(ctx *rpctypes.Context) (*ctypes.ResultHealth, error)
|
||||
|
||||
func makeHealthFunc(c *lrpc.Client) rpcHealthFunc {
|
||||
return func(ctx *rpctypes.Context) (*ctypes.ResultHealth, error) {
|
||||
return c.Health()
|
||||
return c.Health(ctx.Context())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -62,7 +62,7 @@ type rpcStatusFunc func(ctx *rpctypes.Context) (*ctypes.ResultStatus, error)
|
||||
// nolint: interfacer
|
||||
func makeStatusFunc(c *lrpc.Client) rpcStatusFunc {
|
||||
return func(ctx *rpctypes.Context) (*ctypes.ResultStatus, error) {
|
||||
return c.Status()
|
||||
return c.Status(ctx.Context())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -70,7 +70,7 @@ type rpcNetInfoFunc func(ctx *rpctypes.Context, minHeight, maxHeight int64) (*ct
|
||||
|
||||
func makeNetInfoFunc(c *lrpc.Client) rpcNetInfoFunc {
|
||||
return func(ctx *rpctypes.Context, minHeight, maxHeight int64) (*ctypes.ResultNetInfo, error) {
|
||||
return c.NetInfo()
|
||||
return c.NetInfo(ctx.Context())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -78,7 +78,7 @@ type rpcBlockchainInfoFunc func(ctx *rpctypes.Context, minHeight, maxHeight int6
|
||||
|
||||
func makeBlockchainInfoFunc(c *lrpc.Client) rpcBlockchainInfoFunc {
|
||||
return func(ctx *rpctypes.Context, minHeight, maxHeight int64) (*ctypes.ResultBlockchainInfo, error) {
|
||||
return c.BlockchainInfo(minHeight, maxHeight)
|
||||
return c.BlockchainInfo(ctx.Context(), minHeight, maxHeight)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -86,7 +86,7 @@ type rpcGenesisFunc func(ctx *rpctypes.Context) (*ctypes.ResultGenesis, error)
|
||||
|
||||
func makeGenesisFunc(c *lrpc.Client) rpcGenesisFunc {
|
||||
return func(ctx *rpctypes.Context) (*ctypes.ResultGenesis, error) {
|
||||
return c.Genesis()
|
||||
return c.Genesis(ctx.Context())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -94,7 +94,7 @@ type rpcBlockFunc func(ctx *rpctypes.Context, height *int64) (*ctypes.ResultBloc
|
||||
|
||||
func makeBlockFunc(c *lrpc.Client) rpcBlockFunc {
|
||||
return func(ctx *rpctypes.Context, height *int64) (*ctypes.ResultBlock, error) {
|
||||
return c.Block(height)
|
||||
return c.Block(ctx.Context(), height)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -102,7 +102,7 @@ type rpcBlockByHashFunc func(ctx *rpctypes.Context, hash []byte) (*ctypes.Result
|
||||
|
||||
func makeBlockByHashFunc(c *lrpc.Client) rpcBlockByHashFunc {
|
||||
return func(ctx *rpctypes.Context, hash []byte) (*ctypes.ResultBlock, error) {
|
||||
return c.BlockByHash(hash)
|
||||
return c.BlockByHash(ctx.Context(), hash)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -110,7 +110,7 @@ type rpcBlockResultsFunc func(ctx *rpctypes.Context, height *int64) (*ctypes.Res
|
||||
|
||||
func makeBlockResultsFunc(c *lrpc.Client) rpcBlockResultsFunc {
|
||||
return func(ctx *rpctypes.Context, height *int64) (*ctypes.ResultBlockResults, error) {
|
||||
return c.BlockResults(height)
|
||||
return c.BlockResults(ctx.Context(), height)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -118,7 +118,7 @@ type rpcCommitFunc func(ctx *rpctypes.Context, height *int64) (*ctypes.ResultCom
|
||||
|
||||
func makeCommitFunc(c *lrpc.Client) rpcCommitFunc {
|
||||
return func(ctx *rpctypes.Context, height *int64) (*ctypes.ResultCommit, error) {
|
||||
return c.Commit(height)
|
||||
return c.Commit(ctx.Context(), height)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -126,7 +126,7 @@ type rpcTxFunc func(ctx *rpctypes.Context, hash []byte, prove bool) (*ctypes.Res
|
||||
|
||||
func makeTxFunc(c *lrpc.Client) rpcTxFunc {
|
||||
return func(ctx *rpctypes.Context, hash []byte, prove bool) (*ctypes.ResultTx, error) {
|
||||
return c.Tx(hash, prove)
|
||||
return c.Tx(ctx.Context(), hash, prove)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -136,7 +136,7 @@ type rpcTxSearchFunc func(ctx *rpctypes.Context, query string, prove bool,
|
||||
func makeTxSearchFunc(c *lrpc.Client) rpcTxSearchFunc {
|
||||
return func(ctx *rpctypes.Context, query string, prove bool, page, perPage *int, orderBy string) (
|
||||
*ctypes.ResultTxSearch, error) {
|
||||
return c.TxSearch(query, prove, page, perPage, orderBy)
|
||||
return c.TxSearch(ctx.Context(), query, prove, page, perPage, orderBy)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -145,7 +145,7 @@ type rpcValidatorsFunc func(ctx *rpctypes.Context, height *int64,
|
||||
|
||||
func makeValidatorsFunc(c *lrpc.Client) rpcValidatorsFunc {
|
||||
return func(ctx *rpctypes.Context, height *int64, page, perPage *int) (*ctypes.ResultValidators, error) {
|
||||
return c.Validators(height, page, perPage)
|
||||
return c.Validators(ctx.Context(), height, page, perPage)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -153,7 +153,7 @@ type rpcDumpConsensusStateFunc func(ctx *rpctypes.Context) (*ctypes.ResultDumpCo
|
||||
|
||||
func makeDumpConsensusStateFunc(c *lrpc.Client) rpcDumpConsensusStateFunc {
|
||||
return func(ctx *rpctypes.Context) (*ctypes.ResultDumpConsensusState, error) {
|
||||
return c.DumpConsensusState()
|
||||
return c.DumpConsensusState(ctx.Context())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -161,7 +161,7 @@ type rpcConsensusStateFunc func(ctx *rpctypes.Context) (*ctypes.ResultConsensusS
|
||||
|
||||
func makeConsensusStateFunc(c *lrpc.Client) rpcConsensusStateFunc {
|
||||
return func(ctx *rpctypes.Context) (*ctypes.ResultConsensusState, error) {
|
||||
return c.ConsensusState()
|
||||
return c.ConsensusState(ctx.Context())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -169,7 +169,7 @@ type rpcConsensusParamsFunc func(ctx *rpctypes.Context, height *int64) (*ctypes.
|
||||
|
||||
func makeConsensusParamsFunc(c *lrpc.Client) rpcConsensusParamsFunc {
|
||||
return func(ctx *rpctypes.Context, height *int64) (*ctypes.ResultConsensusParams, error) {
|
||||
return c.ConsensusParams(height)
|
||||
return c.ConsensusParams(ctx.Context(), height)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -177,7 +177,7 @@ type rpcUnconfirmedTxsFunc func(ctx *rpctypes.Context, limit *int) (*ctypes.Resu
|
||||
|
||||
func makeUnconfirmedTxsFunc(c *lrpc.Client) rpcUnconfirmedTxsFunc {
|
||||
return func(ctx *rpctypes.Context, limit *int) (*ctypes.ResultUnconfirmedTxs, error) {
|
||||
return c.UnconfirmedTxs(limit)
|
||||
return c.UnconfirmedTxs(ctx.Context(), limit)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -185,7 +185,7 @@ type rpcNumUnconfirmedTxsFunc func(ctx *rpctypes.Context) (*ctypes.ResultUnconfi
|
||||
|
||||
func makeNumUnconfirmedTxsFunc(c *lrpc.Client) rpcNumUnconfirmedTxsFunc {
|
||||
return func(ctx *rpctypes.Context) (*ctypes.ResultUnconfirmedTxs, error) {
|
||||
return c.NumUnconfirmedTxs()
|
||||
return c.NumUnconfirmedTxs(ctx.Context())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -193,7 +193,7 @@ type rpcBroadcastTxCommitFunc func(ctx *rpctypes.Context, tx types.Tx) (*ctypes.
|
||||
|
||||
func makeBroadcastTxCommitFunc(c *lrpc.Client) rpcBroadcastTxCommitFunc {
|
||||
return func(ctx *rpctypes.Context, tx types.Tx) (*ctypes.ResultBroadcastTxCommit, error) {
|
||||
return c.BroadcastTxCommit(tx)
|
||||
return c.BroadcastTxCommit(ctx.Context(), tx)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -201,7 +201,7 @@ type rpcBroadcastTxSyncFunc func(ctx *rpctypes.Context, tx types.Tx) (*ctypes.Re
|
||||
|
||||
func makeBroadcastTxSyncFunc(c *lrpc.Client) rpcBroadcastTxSyncFunc {
|
||||
return func(ctx *rpctypes.Context, tx types.Tx) (*ctypes.ResultBroadcastTx, error) {
|
||||
return c.BroadcastTxSync(tx)
|
||||
return c.BroadcastTxSync(ctx.Context(), tx)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -209,7 +209,7 @@ type rpcBroadcastTxAsyncFunc func(ctx *rpctypes.Context, tx types.Tx) (*ctypes.R
|
||||
|
||||
func makeBroadcastTxAsyncFunc(c *lrpc.Client) rpcBroadcastTxAsyncFunc {
|
||||
return func(ctx *rpctypes.Context, tx types.Tx) (*ctypes.ResultBroadcastTx, error) {
|
||||
return c.BroadcastTxAsync(tx)
|
||||
return c.BroadcastTxAsync(ctx.Context(), tx)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -217,7 +217,7 @@ type rpcABCIQueryFunc func(ctx *rpctypes.Context, path string, data bytes.HexByt
|
||||
|
||||
func makeABCIQueryFunc(c *lrpc.Client) rpcABCIQueryFunc {
|
||||
return func(ctx *rpctypes.Context, path string, data bytes.HexBytes) (*ctypes.ResultABCIQuery, error) {
|
||||
return c.ABCIQuery(path, data)
|
||||
return c.ABCIQuery(ctx.Context(), path, data)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -225,7 +225,7 @@ type rpcABCIInfoFunc func(ctx *rpctypes.Context) (*ctypes.ResultABCIInfo, error)
|
||||
|
||||
func makeABCIInfoFunc(c *lrpc.Client) rpcABCIInfoFunc {
|
||||
return func(ctx *rpctypes.Context) (*ctypes.ResultABCIInfo, error) {
|
||||
return c.ABCIInfo()
|
||||
return c.ABCIInfo(ctx.Context())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -234,6 +234,6 @@ type rpcBroadcastEvidenceFunc func(ctx *rpctypes.Context, ev types.Evidence) (*c
|
||||
// nolint: interfacer
|
||||
func makeBroadcastEvidenceFunc(c *lrpc.Client) rpcBroadcastEvidenceFunc {
|
||||
return func(ctx *rpctypes.Context, ev types.Evidence) (*ctypes.ResultBroadcastEvidence, error) {
|
||||
return c.BroadcastEvidence(ev)
|
||||
return c.BroadcastEvidence(ctx.Context(), ev)
|
||||
}
|
||||
}
|
||||
|
||||
+62
-62
@@ -61,24 +61,24 @@ func (c *Client) OnStop() {
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Client) Status() (*ctypes.ResultStatus, error) {
|
||||
return c.next.Status()
|
||||
func (c *Client) Status(ctx context.Context) (*ctypes.ResultStatus, error) {
|
||||
return c.next.Status(ctx)
|
||||
}
|
||||
|
||||
func (c *Client) ABCIInfo() (*ctypes.ResultABCIInfo, error) {
|
||||
return c.next.ABCIInfo()
|
||||
func (c *Client) ABCIInfo(ctx context.Context) (*ctypes.ResultABCIInfo, error) {
|
||||
return c.next.ABCIInfo(ctx)
|
||||
}
|
||||
|
||||
func (c *Client) ABCIQuery(path string, data tmbytes.HexBytes) (*ctypes.ResultABCIQuery, error) {
|
||||
return c.ABCIQueryWithOptions(path, data, rpcclient.DefaultABCIQueryOptions)
|
||||
func (c *Client) ABCIQuery(ctx context.Context, path string, data tmbytes.HexBytes) (*ctypes.ResultABCIQuery, error) {
|
||||
return c.ABCIQueryWithOptions(ctx, path, data, rpcclient.DefaultABCIQueryOptions)
|
||||
}
|
||||
|
||||
// GetWithProofOptions is useful if you want full access to the ABCIQueryOptions.
|
||||
// XXX Usage of path? It's not used, and sometimes it's /, sometimes /key, sometimes /store.
|
||||
func (c *Client) ABCIQueryWithOptions(path string, data tmbytes.HexBytes,
|
||||
func (c *Client) ABCIQueryWithOptions(ctx context.Context, path string, data tmbytes.HexBytes,
|
||||
opts rpcclient.ABCIQueryOptions) (*ctypes.ResultABCIQuery, error) {
|
||||
|
||||
res, err := c.next.ABCIQueryWithOptions(path, data, opts)
|
||||
res, err := c.next.ABCIQueryWithOptions(ctx, path, data, opts)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -97,7 +97,7 @@ func (c *Client) ABCIQueryWithOptions(path string, data tmbytes.HexBytes,
|
||||
|
||||
// Update the light client if we're behind.
|
||||
// NOTE: AppHash for height H is in header H+1.
|
||||
l, err := c.updateLightClientIfNeededTo(resp.Height + 1)
|
||||
l, err := c.updateLightClientIfNeededTo(ctx, resp.Height+1)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -129,44 +129,44 @@ func (c *Client) ABCIQueryWithOptions(path string, data tmbytes.HexBytes,
|
||||
return &ctypes.ResultABCIQuery{Response: resp}, nil
|
||||
}
|
||||
|
||||
func (c *Client) BroadcastTxCommit(tx types.Tx) (*ctypes.ResultBroadcastTxCommit, error) {
|
||||
return c.next.BroadcastTxCommit(tx)
|
||||
func (c *Client) BroadcastTxCommit(ctx context.Context, tx types.Tx) (*ctypes.ResultBroadcastTxCommit, error) {
|
||||
return c.next.BroadcastTxCommit(ctx, tx)
|
||||
}
|
||||
|
||||
func (c *Client) BroadcastTxAsync(tx types.Tx) (*ctypes.ResultBroadcastTx, error) {
|
||||
return c.next.BroadcastTxAsync(tx)
|
||||
func (c *Client) BroadcastTxAsync(ctx context.Context, tx types.Tx) (*ctypes.ResultBroadcastTx, error) {
|
||||
return c.next.BroadcastTxAsync(ctx, tx)
|
||||
}
|
||||
|
||||
func (c *Client) BroadcastTxSync(tx types.Tx) (*ctypes.ResultBroadcastTx, error) {
|
||||
return c.next.BroadcastTxSync(tx)
|
||||
func (c *Client) BroadcastTxSync(ctx context.Context, tx types.Tx) (*ctypes.ResultBroadcastTx, error) {
|
||||
return c.next.BroadcastTxSync(ctx, tx)
|
||||
}
|
||||
|
||||
func (c *Client) UnconfirmedTxs(limit *int) (*ctypes.ResultUnconfirmedTxs, error) {
|
||||
return c.next.UnconfirmedTxs(limit)
|
||||
func (c *Client) UnconfirmedTxs(ctx context.Context, limit *int) (*ctypes.ResultUnconfirmedTxs, error) {
|
||||
return c.next.UnconfirmedTxs(ctx, limit)
|
||||
}
|
||||
|
||||
func (c *Client) NumUnconfirmedTxs() (*ctypes.ResultUnconfirmedTxs, error) {
|
||||
return c.next.NumUnconfirmedTxs()
|
||||
func (c *Client) NumUnconfirmedTxs(ctx context.Context) (*ctypes.ResultUnconfirmedTxs, error) {
|
||||
return c.next.NumUnconfirmedTxs(ctx)
|
||||
}
|
||||
|
||||
func (c *Client) CheckTx(tx types.Tx) (*ctypes.ResultCheckTx, error) {
|
||||
return c.next.CheckTx(tx)
|
||||
func (c *Client) CheckTx(ctx context.Context, tx types.Tx) (*ctypes.ResultCheckTx, error) {
|
||||
return c.next.CheckTx(ctx, tx)
|
||||
}
|
||||
|
||||
func (c *Client) NetInfo() (*ctypes.ResultNetInfo, error) {
|
||||
return c.next.NetInfo()
|
||||
func (c *Client) NetInfo(ctx context.Context) (*ctypes.ResultNetInfo, error) {
|
||||
return c.next.NetInfo(ctx)
|
||||
}
|
||||
|
||||
func (c *Client) DumpConsensusState() (*ctypes.ResultDumpConsensusState, error) {
|
||||
return c.next.DumpConsensusState()
|
||||
func (c *Client) DumpConsensusState(ctx context.Context) (*ctypes.ResultDumpConsensusState, error) {
|
||||
return c.next.DumpConsensusState(ctx)
|
||||
}
|
||||
|
||||
func (c *Client) ConsensusState() (*ctypes.ResultConsensusState, error) {
|
||||
return c.next.ConsensusState()
|
||||
func (c *Client) ConsensusState(ctx context.Context) (*ctypes.ResultConsensusState, error) {
|
||||
return c.next.ConsensusState(ctx)
|
||||
}
|
||||
|
||||
func (c *Client) ConsensusParams(height *int64) (*ctypes.ResultConsensusParams, error) {
|
||||
res, err := c.next.ConsensusParams(height)
|
||||
func (c *Client) ConsensusParams(ctx context.Context, height *int64) (*ctypes.ResultConsensusParams, error) {
|
||||
res, err := c.next.ConsensusParams(ctx, height)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -180,7 +180,7 @@ func (c *Client) ConsensusParams(height *int64) (*ctypes.ResultConsensusParams,
|
||||
}
|
||||
|
||||
// Update the light client if we're behind.
|
||||
l, err := c.updateLightClientIfNeededTo(res.BlockHeight)
|
||||
l, err := c.updateLightClientIfNeededTo(ctx, res.BlockHeight)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -194,14 +194,14 @@ func (c *Client) ConsensusParams(height *int64) (*ctypes.ResultConsensusParams,
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func (c *Client) Health() (*ctypes.ResultHealth, error) {
|
||||
return c.next.Health()
|
||||
func (c *Client) Health(ctx context.Context) (*ctypes.ResultHealth, error) {
|
||||
return c.next.Health(ctx)
|
||||
}
|
||||
|
||||
// BlockchainInfo calls rpcclient#BlockchainInfo and then verifies every header
|
||||
// returned.
|
||||
func (c *Client) BlockchainInfo(minHeight, maxHeight int64) (*ctypes.ResultBlockchainInfo, error) {
|
||||
res, err := c.next.BlockchainInfo(minHeight, maxHeight)
|
||||
func (c *Client) BlockchainInfo(ctx context.Context, minHeight, maxHeight int64) (*ctypes.ResultBlockchainInfo, error) {
|
||||
res, err := c.next.BlockchainInfo(ctx, minHeight, maxHeight)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -219,7 +219,7 @@ func (c *Client) BlockchainInfo(minHeight, maxHeight int64) (*ctypes.ResultBlock
|
||||
// Update the light client if we're behind.
|
||||
if len(res.BlockMetas) > 0 {
|
||||
lastHeight := res.BlockMetas[len(res.BlockMetas)-1].Header.Height
|
||||
if _, err := c.updateLightClientIfNeededTo(lastHeight); err != nil {
|
||||
if _, err := c.updateLightClientIfNeededTo(ctx, lastHeight); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
@@ -239,13 +239,13 @@ func (c *Client) BlockchainInfo(minHeight, maxHeight int64) (*ctypes.ResultBlock
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func (c *Client) Genesis() (*ctypes.ResultGenesis, error) {
|
||||
return c.next.Genesis()
|
||||
func (c *Client) Genesis(ctx context.Context) (*ctypes.ResultGenesis, error) {
|
||||
return c.next.Genesis(ctx)
|
||||
}
|
||||
|
||||
// Block calls rpcclient#Block and then verifies the result.
|
||||
func (c *Client) Block(height *int64) (*ctypes.ResultBlock, error) {
|
||||
res, err := c.next.Block(height)
|
||||
func (c *Client) Block(ctx context.Context, height *int64) (*ctypes.ResultBlock, error) {
|
||||
res, err := c.next.Block(ctx, height)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -263,7 +263,7 @@ func (c *Client) Block(height *int64) (*ctypes.ResultBlock, error) {
|
||||
}
|
||||
|
||||
// Update the light client if we're behind.
|
||||
l, err := c.updateLightClientIfNeededTo(res.Block.Height)
|
||||
l, err := c.updateLightClientIfNeededTo(ctx, res.Block.Height)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -278,8 +278,8 @@ func (c *Client) Block(height *int64) (*ctypes.ResultBlock, error) {
|
||||
}
|
||||
|
||||
// BlockByHash calls rpcclient#BlockByHash and then verifies the result.
|
||||
func (c *Client) BlockByHash(hash []byte) (*ctypes.ResultBlock, error) {
|
||||
res, err := c.next.BlockByHash(hash)
|
||||
func (c *Client) BlockByHash(ctx context.Context, hash []byte) (*ctypes.ResultBlock, error) {
|
||||
res, err := c.next.BlockByHash(ctx, hash)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -297,7 +297,7 @@ func (c *Client) BlockByHash(hash []byte) (*ctypes.ResultBlock, error) {
|
||||
}
|
||||
|
||||
// Update the light client if we're behind.
|
||||
l, err := c.updateLightClientIfNeededTo(res.Block.Height)
|
||||
l, err := c.updateLightClientIfNeededTo(ctx, res.Block.Height)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -313,10 +313,10 @@ func (c *Client) BlockByHash(hash []byte) (*ctypes.ResultBlock, error) {
|
||||
|
||||
// BlockResults returns the block results for the given height. If no height is
|
||||
// provided, the results of the block preceding the latest are returned.
|
||||
func (c *Client) BlockResults(height *int64) (*ctypes.ResultBlockResults, error) {
|
||||
func (c *Client) BlockResults(ctx context.Context, height *int64) (*ctypes.ResultBlockResults, error) {
|
||||
var h int64
|
||||
if height == nil {
|
||||
res, err := c.next.Status()
|
||||
res, err := c.next.Status(ctx)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("can't get latest height: %w", err)
|
||||
}
|
||||
@@ -327,7 +327,7 @@ func (c *Client) BlockResults(height *int64) (*ctypes.ResultBlockResults, error)
|
||||
h = *height
|
||||
}
|
||||
|
||||
res, err := c.next.BlockResults(&h)
|
||||
res, err := c.next.BlockResults(ctx, &h)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -338,7 +338,7 @@ func (c *Client) BlockResults(height *int64) (*ctypes.ResultBlockResults, error)
|
||||
}
|
||||
|
||||
// Update the light client if we're behind.
|
||||
trustedBlock, err := c.updateLightClientIfNeededTo(h + 1)
|
||||
trustedBlock, err := c.updateLightClientIfNeededTo(ctx, h+1)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -374,8 +374,8 @@ func (c *Client) BlockResults(height *int64) (*ctypes.ResultBlockResults, error)
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func (c *Client) Commit(height *int64) (*ctypes.ResultCommit, error) {
|
||||
res, err := c.next.Commit(height)
|
||||
func (c *Client) Commit(ctx context.Context, height *int64) (*ctypes.ResultCommit, error) {
|
||||
res, err := c.next.Commit(ctx, height)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -389,7 +389,7 @@ func (c *Client) Commit(height *int64) (*ctypes.ResultCommit, error) {
|
||||
}
|
||||
|
||||
// Update the light client if we're behind.
|
||||
l, err := c.updateLightClientIfNeededTo(res.Height)
|
||||
l, err := c.updateLightClientIfNeededTo(ctx, res.Height)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -405,8 +405,8 @@ func (c *Client) Commit(height *int64) (*ctypes.ResultCommit, error) {
|
||||
|
||||
// Tx calls rpcclient#Tx method and then verifies the proof if such was
|
||||
// requested.
|
||||
func (c *Client) Tx(hash []byte, prove bool) (*ctypes.ResultTx, error) {
|
||||
res, err := c.next.Tx(hash, prove)
|
||||
func (c *Client) Tx(ctx context.Context, hash []byte, prove bool) (*ctypes.ResultTx, error) {
|
||||
res, err := c.next.Tx(ctx, hash, prove)
|
||||
if err != nil || !prove {
|
||||
return res, err
|
||||
}
|
||||
@@ -417,7 +417,7 @@ func (c *Client) Tx(hash []byte, prove bool) (*ctypes.ResultTx, error) {
|
||||
}
|
||||
|
||||
// Update the light client if we're behind.
|
||||
l, err := c.updateLightClientIfNeededTo(res.Height)
|
||||
l, err := c.updateLightClientIfNeededTo(ctx, res.Height)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -426,17 +426,17 @@ func (c *Client) Tx(hash []byte, prove bool) (*ctypes.ResultTx, error) {
|
||||
return res, res.Proof.Validate(l.DataHash)
|
||||
}
|
||||
|
||||
func (c *Client) TxSearch(query string, prove bool, page, perPage *int, orderBy string) (
|
||||
func (c *Client) TxSearch(ctx context.Context, query string, prove bool, page, perPage *int, orderBy string) (
|
||||
*ctypes.ResultTxSearch, error) {
|
||||
return c.next.TxSearch(query, prove, page, perPage, orderBy)
|
||||
return c.next.TxSearch(ctx, query, prove, page, perPage, orderBy)
|
||||
}
|
||||
|
||||
// Validators fetches and verifies validators.
|
||||
//
|
||||
// WARNING: only full validator sets are verified (when length of validators is
|
||||
// less than +perPage+. +perPage+ default is 30, max is 100).
|
||||
func (c *Client) Validators(height *int64, page, perPage *int) (*ctypes.ResultValidators, error) {
|
||||
res, err := c.next.Validators(height, page, perPage)
|
||||
func (c *Client) Validators(ctx context.Context, height *int64, page, perPage *int) (*ctypes.ResultValidators, error) {
|
||||
res, err := c.next.Validators(ctx, height, page, perPage)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -454,7 +454,7 @@ func (c *Client) Validators(height *int64, page, perPage *int) (*ctypes.ResultVa
|
||||
}
|
||||
|
||||
// Update the light client if we're behind.
|
||||
l, err := c.updateLightClientIfNeededTo(updateHeight)
|
||||
l, err := c.updateLightClientIfNeededTo(ctx, updateHeight)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -480,8 +480,8 @@ func (c *Client) Validators(height *int64, page, perPage *int) (*ctypes.ResultVa
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func (c *Client) BroadcastEvidence(ev types.Evidence) (*ctypes.ResultBroadcastEvidence, error) {
|
||||
return c.next.BroadcastEvidence(ev)
|
||||
func (c *Client) BroadcastEvidence(ctx context.Context, ev types.Evidence) (*ctypes.ResultBroadcastEvidence, error) {
|
||||
return c.next.BroadcastEvidence(ctx, ev)
|
||||
}
|
||||
|
||||
func (c *Client) Subscribe(ctx context.Context, subscriber, query string,
|
||||
@@ -497,8 +497,8 @@ func (c *Client) UnsubscribeAll(ctx context.Context, subscriber string) error {
|
||||
return c.next.UnsubscribeAll(ctx, subscriber)
|
||||
}
|
||||
|
||||
func (c *Client) updateLightClientIfNeededTo(height int64) (*types.LightBlock, error) {
|
||||
l, err := c.lc.VerifyLightBlockAtHeight(height, time.Now())
|
||||
func (c *Client) updateLightClientIfNeededTo(ctx context.Context, height int64) (*types.LightBlock, error) {
|
||||
l, err := c.lc.VerifyLightBlockAtHeight(ctx, height, time.Now())
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to update light client to %d: %w", height, err)
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package light
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"github.com/tendermint/tendermint/light/provider"
|
||||
@@ -15,6 +16,7 @@ import (
|
||||
// See all Option(s) for the additional configuration.
|
||||
// See NewClient.
|
||||
func NewHTTPClient(
|
||||
ctx context.Context,
|
||||
chainID string,
|
||||
trustOptions TrustOptions,
|
||||
primaryAddress string,
|
||||
@@ -28,6 +30,7 @@ func NewHTTPClient(
|
||||
}
|
||||
|
||||
return NewClient(
|
||||
ctx,
|
||||
chainID,
|
||||
trustOptions,
|
||||
providers[len(providers)-1],
|
||||
|
||||
Reference in New Issue
Block a user