Repository: lightningnetwork/lnd
Pull request #8101 (2023-10-19 15:30:14)

chainfee: Fix test flake in `TestWebAPIFeeEstimator`
This time we finally get a full understanding of the flakes in `TestWebAPIFeeEstimator`, as shown below, there's a "real" HTTP request sent to github and errored out, resulting in an empty fee map being used by the fee estimator.
```
2023-10-17 18:22:01.112 [WRN] CFEE: Web API does not have a fee rate for target=7, using the fee rate for target=6 instead
2023-10-17 18:22:01.112 [WRN] CFEE: Web API does not have a fee rate for target=5, using the fee rate for target=2 instead
2023-10-17 18:22:01.112 [ERR] CFEE: Web API does not have a fee rate for target=1, using the fee rate for target=2 instead
2023-10-17 18:22:01.112 [ERR] CFEE: Unable to query estimator: web API error: fee rate cache is empty
2023-10-17 18:22:01.112 [DBG] CFEE: Web API returning 253 sat/kw for conf target of 5
2023-10-17 18:22:01.112 [INF] CFEE: Starting web API fee estimator
2023-10-17 18:22:01.112 [DBG] CFEE: Using minimum fee rate of 2000 sat/kw
2023-10-17 18:22:06.117 [ERR] CFEE: unable to query web api for fee response: Get "https://www.github.com": dial tcp: lookup www.github.com: i/o timeout
2023-10-17 18:22:06.117 [ERR] CFEE: Unable to query estimator: web API error: fee rate cache is empty
2023-10-17 18:22:06.117 [DBG] CFEE: Web API returning 253 sat/kw for conf target of 106
2023-10-17 18:22:06.118 [ERR] CFEE: Unable to query estimator: web API error: fee rate cache is empty
2023-10-17 18:22:06.118 [DBG] CFEE: Web API returning 253 sat/kw for conf target of 1
2023-10-17 18:22:06.118 [ERR] CFEE: Unable to query estimator: web API error: fee rate cache is empty
2023-10-17 18:22:06.118 [DBG] CFEE: Web API returning 253 sat/kw for conf target of 6
2023-10-17 18:22:06.118 [INF] CFEE: Stopping web API fee estimator
--- FAIL: TestWebAPIFeeEstimator (5.01s)
    --- FAIL: TestWebAPIFeeEstimator/target_w_too-low_fee (0.00s)
        estimator_test.go:252: 
            	Error Trace:	/home/runner/work/lnd/lnd/lnwallet/chainfee/estimator_test.go:252
            	Error:      	Not equal: 
            	            	expected: 500
            	            	actual  : 253
            	Test:       	TestWebAPIFeeEstimator/target_w_too-low_fee
            	Messages:   	target 106 failed, fee map is map[2:4000 6:2000]
    --- FAIL: TestWebAPIFeeEstimator/API-omitted_target (0.00s)
        estimator_test.go:252: 
            	Error Trace:	/home/runner/work/lnd/lnd/lnwallet/chainfee/estimator_test.go:252
            	Error:      	Not equal: 
            	            	expected: 1000
            	            	actual  : 253
            	Test:       	TestWebAPIFeeEstimator/API-omitted_target
            	Messages:   	target 1 failed, fee map is map[2:4000 6:2000]
    --- FAIL: TestWebAPIFeeEstimator/valid_target (0.00s)
        estimator_test.go:252: 
            	Error Trace:	/home/runner/work/lnd/lnd/lnwallet/chainfee/estimator_test.go:252
            	Error:      	Not equal: 
            	            	expected: 500
            	            	actual  : 253
            	Test:       	TestWebAPIFeeEstimator/valid_target
            	Messages:   	target 6 failed, fee map is map[2:4000 6:2000]
FAIL
FAIL	github.com/lightningnetwork/lnd/lnwallet/chainfee	5.010s
FAIL
```

To fix it, a minor refactor is applied so our web API only cares about the fee maps returned, and leaves the implementation details to the api source.



Patch:
diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml
index 1dbf0f54f..31a594c3a 100644
--- a/.github/workflows/main.yml
+++ b/.github/workflows/main.yml
@@ -329,8 +329,8 @@ jobs:
       fail-fast: false
       matrix:
         pinned_dep:
-          - google.golang.org/grpc v1.56.3
-          - github.com/golang/protobuf v1.5.3
+          - google.golang.org/grpc v1.53.0
+          - github.com/golang/protobuf v1.5.2
 
     steps:
       - name: git checkout
diff --git a/cmd/lncli/chainrpc_active.go b/cmd/lncli/chainrpc_active.go
index 48946e0d5..0d8b891ac 100644
--- a/cmd/lncli/chainrpc_active.go
+++ b/cmd/lncli/chainrpc_active.go
@@ -25,7 +25,6 @@ func chainCommands() []cli.Command {
 				getBlockCommand,
 				getBestBlockCommand,
 				getBlockHashCommand,
-				getBlockHeaderCommand,
 			},
 		},
 	}
@@ -114,45 +113,6 @@ func getBlock(ctx *cli.Context) error {
 	return nil
 }
 
-var getBlockHeaderCommand = cli.Command{
-	Name:        "getblockheader",
-	Usage:       "Get a block header.",
-	Category:    "On-chain",
-	Description: "Returns a block header with a particular block hash.",
-	ArgsUsage:   "hash",
-	Action:      actionDecorator(getBlockHeader),
-}
-
-func getBlockHeader(ctx *cli.Context) error {
-	ctxc := getContext()
-	args := ctx.Args()
-
-	// Display the command's help message if we do not have the expected
-	// number of arguments/flags.
-	if !args.Present() {
-		return cli.ShowCommandHelp(ctx, "getblockheader")
-	}
-
-	blockHash, err := chainhash.NewHashFromStr(args.First())
-	if err != nil {
-		return err
-	}
-
-	req := &chainrpc.GetBlockHeaderRequest{BlockHash: blockHash[:]}
-
-	client, cleanUp := getChainClient(ctx)
-	defer cleanUp()
-
-	resp, err := client.GetBlockHeader(ctxc, req)
-	if err != nil {
-		return err
-	}
-
-	printRespJSON(resp)
-
-	return nil
-}
-
 var getBestBlockCommand = cli.Command{
 	Name:     "getbestblock",
 	Category: "On-chain",
diff --git a/cmd/lncli/neutrino_active.go b/cmd/lncli/neutrino_active.go
index 099da46c6..4267738e1 100644
--- a/cmd/lncli/neutrino_active.go
+++ b/cmd/lncli/neutrino_active.go
@@ -155,16 +155,16 @@ func isBanned(ctx *cli.Context) error {
 	return nil
 }
 
-var getBlockHeaderNeutrinoCommand = cli.Command{
+var getBlockHeaderCommand = cli.Command{
 	Name:        "getblockheader",
 	Usage:       "Get a block header.",
 	Category:    "Neutrino",
 	Description: "Returns a block header with a particular block hash.",
 	ArgsUsage:   "hash",
-	Action:      actionDecorator(getBlockHeaderNeutrino),
+	Action:      actionDecorator(getBlockHeader),
 }
 
-func getBlockHeaderNeutrino(ctx *cli.Context) error {
+func getBlockHeader(ctx *cli.Context) error {
 	ctxc := getContext()
 	args := ctx.Args()
 
@@ -239,7 +239,7 @@ func neutrinoCommands() []cli.Command {
 				addPeerCommand,
 				disconnectPeerCommand,
 				isBannedCommand,
-				getBlockHeaderNeutrinoCommand,
+				getBlockHeaderCommand,
 				getCFilterCommand,
 			},
 		},
diff --git a/docs/release-notes/release-notes-0.17.1.md b/docs/release-notes/release-notes-0.17.1.md
index 2caf937c6..a0e414f05 100644
--- a/docs/release-notes/release-notes-0.17.1.md
+++ b/docs/release-notes/release-notes-0.17.1.md
@@ -36,10 +36,6 @@
   instead.
 
 ## RPC Additions
-
-* [`chainrpc` `GetBlockHeader`](https://github.com/lightningnetwork/lnd/pull/8111)
-  can be used to get block headers with any chain backend.
-
 ## lncli Additions
 
 # Improvements
diff --git a/go.mod b/go.mod
index 6624a9211..5d3e67b70 100644
--- a/go.mod
+++ b/go.mod
@@ -60,7 +60,7 @@ require (
 	golang.org/x/sync v0.2.0
 	golang.org/x/term v0.13.0
 	golang.org/x/time v0.0.0-20220224211638-0e9765cccd65
-	google.golang.org/grpc v1.56.3
+	google.golang.org/grpc v1.53.0
 	google.golang.org/protobuf v1.30.0
 	gopkg.in/macaroon-bakery.v2 v2.0.1
 	gopkg.in/macaroon.v2 v2.0.0
@@ -98,7 +98,7 @@ require (
 	github.com/fsnotify/fsnotify v1.5.4 // indirect
 	github.com/gogo/protobuf v1.3.2 // indirect
 	github.com/golang-jwt/jwt/v4 v4.4.2 // indirect
-	github.com/golang/protobuf v1.5.3 // indirect
+	github.com/golang/protobuf v1.5.2 // indirect
 	github.com/golang/snappy v0.0.4 // indirect
 	github.com/google/btree v1.0.1 // indirect
 	github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect
@@ -180,7 +180,7 @@ require (
 	golang.org/x/sys v0.13.0 // indirect
 	golang.org/x/text v0.13.0 // indirect
 	golang.org/x/tools v0.9.1 // indirect
-	google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1 // indirect
+	google.golang.org/genproto v0.0.0-20230110181048-76db0878b65f // indirect
 	gopkg.in/errgo.v1 v1.0.1 // indirect
 	gopkg.in/natefinch/lumberjack.v2 v2.0.0 // indirect
 	gopkg.in/yaml.v2 v2.4.0 // indirect
diff --git a/go.sum b/go.sum
index 16f94f9d3..f1ecf512e 100644
--- a/go.sum
+++ b/go.sum
@@ -13,14 +13,14 @@ cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKV
 cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs=
 cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc=
 cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY=
-cloud.google.com/go v0.110.0 h1:Zc8gqp3+a9/Eyph2KDmcGaPtbKRIoqq4YTlL4NMD0Ys=
+cloud.google.com/go v0.107.0 h1:qkj22L7bgkl6vIeZDlOY2po43Mx/TIa2Wsa7VR+PEww=
 cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o=
 cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE=
 cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc=
 cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg=
 cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc=
 cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ=
-cloud.google.com/go/compute v1.19.1 h1:am86mquDUgjGNWxiGn+5PGLbmgiWXlE/yNWpIpNvuXY=
+cloud.google.com/go/compute v1.15.1 h1:7UGq3QknM33pw5xATlpzeoomNxsacIVvTqTTvbfajmE=
 cloud.google.com/go/compute/metadata v0.2.3 h1:mg4jlk7mCAj6xXp9UJ4fjI9VUI5rubuGBW5aJ7UnBMY=
 cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE=
 cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk=
@@ -139,7 +139,6 @@ github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGX
 github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
 github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
 github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
-github.com/cncf/xds/go v0.0.0-20230607035331-e9ce68804cb4 h1:/inchEIKaYC1Akx+H+gqO04wryn5h75LSazbRlnya1k=
 github.com/cockroachdb/apd v1.1.0 h1:3LFP3629v+1aKXU5Q37mxmRxX/pIu1nijXydLShEq5I=
 github.com/cockroachdb/apd v1.1.0/go.mod h1:8Sl8LxpKi29FqWXR16WEFZRNSz3SoPzUzeMeY4+DwBQ=
 github.com/cockroachdb/datadriven v0.0.0-20200714090401-bf6692d28da5 h1:xD/lrqdvwsc+O2bjSSi3YqY73Ke3LAiSCx49aCesA0E=
@@ -195,7 +194,6 @@ github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.m
 github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ=
 github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0=
 github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
-github.com/envoyproxy/protoc-gen-validate v0.10.1 h1:c0g45+xCJhdgFGw7a5QAfdS4byAbud7miNWJ1WwEVf8=
 github.com/fergusstrange/embedded-postgres v1.10.0 h1:YnwF6xAQYmKLAXXrrRx4rHDLih47YJwVPvg8jeKfdNg=
 github.com/fergusstrange/embedded-postgres v1.10.0/go.mod h1:a008U8/Rws5FtIOTGYDYa7beVWsT3qVKyqExqYYjL+c=
 github.com/frankban/quicktest v1.2.2/go.mod h1:Qh/WofXFeiAFII1aEBu529AtJo6Zg2VHscnEsbBnJ20=
@@ -232,7 +230,7 @@ github.com/golang-migrate/migrate/v4 v4.16.1 h1:O+0C55RbMN66pWm5MjO6mw0px6usGpY0
 github.com/golang-migrate/migrate/v4 v4.16.1/go.mod h1:qXiwa/3Zeqaltm1MxOCZDYysW/F6folYiBgBG03l9hc=
 github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
 github.com/golang/glog v0.0.0-20210429001901-424d2337a529/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
-github.com/golang/glog v1.1.0 h1:/d3pCKDPWNnvIWe0vVUpNP32qc8U3PDVxySP/y360qE=
+github.com/golang/glog v1.0.0 h1:nfP3RFugxnNRyKgeWd4oI1nYvXpxrx8ck8ZrcizshdQ=
 github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
 github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
 github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
@@ -254,9 +252,8 @@ github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QD
 github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
 github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
 github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
+github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=
 github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
-github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg=
-github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
 github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
 github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM=
 github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
@@ -793,7 +790,7 @@ golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4Iltr
 golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
 golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
 golang.org/x/oauth2 v0.0.0-20210615190721-d04028783cf1/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
-golang.org/x/oauth2 v0.7.0 h1:qe6s0zUXlPX80/dITx3440hWZ7GwMwgDDyrSGTPJG/g=
+golang.org/x/oauth2 v0.4.0 h1:NF0gk8LVPg1Ml7SSbGyySuoxdsXitj7TvgvuRxIMc/M=
 golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@@ -1010,8 +1007,8 @@ google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6D
 google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
 google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
 google.golang.org/genproto v0.0.0-20210617175327-b9e0b3197ced/go.mod h1:SzzZ/N+nwJDaO1kznhnlzqS8ocJICar6hYhVyhi++24=
-google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1 h1:KpwkzHKEF7B9Zxg18WzOa7djJ+Ha5DzthMyZYQfEn2A=
-google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1/go.mod h1:nKE/iIaLqn2bQwXBg8f1g2Ylh6r5MN5CmZvuzZCgsCU=
+google.golang.org/genproto v0.0.0-20230110181048-76db0878b65f h1:BWUVssLB0HVOSY78gIdvk1dTVYtT1y8SBWtPYuTJ/6w=
+google.golang.org/genproto v0.0.0-20230110181048-76db0878b65f/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM=
 google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
 google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
 google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
@@ -1030,8 +1027,8 @@ google.golang.org/grpc v1.37.1/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQ
 google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM=
 google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34=
 google.golang.org/grpc v1.41.0/go.mod h1:U3l9uK9J0sini8mHphKoXyaqDA/8VyGnDee1zzIUK6k=
-google.golang.org/grpc v1.56.3 h1:8I4C0Yq1EjstUzUJzpcRVbuYA2mODtEmpWiQoN/b2nc=
-google.golang.org/grpc v1.56.3/go.mod h1:I9bI3vqKfayGqPUAwGdOSu7kt6oIJLixfffKrpXqQ9s=
+google.golang.org/grpc v1.53.0 h1:LAv2ds7cmFV/XTS3XG1NneeENYrXGmorPxsBbptIjNc=
+google.golang.org/grpc v1.53.0/go.mod h1:OnIrk0ipVdj4N5d9IUoFUx72/VlD7+jUsHwZgwSMQpw=
 gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
 gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
 gopkg.in/check.v1 v1.0.0-20160105164936-4f90aeace3a2/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
diff --git a/kvdb/go.mod b/kvdb/go.mod
index 40727c742..59ca420b9 100644
--- a/kvdb/go.mod
+++ b/kvdb/go.mod
@@ -31,7 +31,7 @@ require (
 	github.com/dustin/go-humanize v1.0.0 // indirect
 	github.com/gogo/protobuf v1.3.2 // indirect
 	github.com/golang-jwt/jwt/v4 v4.4.2 // indirect
-	github.com/golang/protobuf v1.5.3 // indirect
+	github.com/golang/protobuf v1.5.2 // indirect
 	github.com/golang/snappy v0.0.4 // indirect
 	github.com/google/uuid v1.3.0 // indirect
 	github.com/gorilla/websocket v1.4.2 // indirect
@@ -93,8 +93,8 @@ require (
 	golang.org/x/text v0.13.0 // indirect
 	golang.org/x/time v0.0.0-20220224211638-0e9765cccd65 // indirect
 	golang.org/x/tools v0.9.1 // indirect
-	google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1 // indirect
-	google.golang.org/grpc v1.56.3 // indirect
+	google.golang.org/genproto v0.0.0-20230110181048-76db0878b65f // indirect
+	google.golang.org/grpc v1.53.0 // indirect
 	google.golang.org/protobuf v1.30.0 // indirect
 	gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect
 	gopkg.in/natefinch/lumberjack.v2 v2.0.0 // indirect
diff --git a/kvdb/go.sum b/kvdb/go.sum
index 7672a3d94..075c8b0af 100644
--- a/kvdb/go.sum
+++ b/kvdb/go.sum
@@ -1,7 +1,7 @@
 cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
 cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
-cloud.google.com/go v0.110.0 h1:Zc8gqp3+a9/Eyph2KDmcGaPtbKRIoqq4YTlL4NMD0Ys=
-cloud.google.com/go/compute v1.19.1 h1:am86mquDUgjGNWxiGn+5PGLbmgiWXlE/yNWpIpNvuXY=
+cloud.google.com/go v0.105.0 h1:DNtEKRBAAzeS4KyIory52wWHuClNaXJ5x1F7xa4q+5Y=
+cloud.google.com/go/compute v1.15.1 h1:7UGq3QknM33pw5xATlpzeoomNxsacIVvTqTTvbfajmE=
 cloud.google.com/go/compute/metadata v0.2.3 h1:mg4jlk7mCAj6xXp9UJ4fjI9VUI5rubuGBW5aJ7UnBMY=
 github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
 github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
@@ -39,7 +39,6 @@ github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGX
 github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
 github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
 github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
-github.com/cncf/xds/go v0.0.0-20230607035331-e9ce68804cb4 h1:/inchEIKaYC1Akx+H+gqO04wryn5h75LSazbRlnya1k=
 github.com/cockroachdb/apd v1.1.0 h1:3LFP3629v+1aKXU5Q37mxmRxX/pIu1nijXydLShEq5I=
 github.com/cockroachdb/apd v1.1.0/go.mod h1:8Sl8LxpKi29FqWXR16WEFZRNSz3SoPzUzeMeY4+DwBQ=
 github.com/cockroachdb/datadriven v0.0.0-20200714090401-bf6692d28da5 h1:xD/lrqdvwsc+O2bjSSi3YqY73Ke3LAiSCx49aCesA0E=
@@ -69,7 +68,6 @@ github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.m
 github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ=
 github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0=
 github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
-github.com/envoyproxy/protoc-gen-validate v0.10.1 h1:c0g45+xCJhdgFGw7a5QAfdS4byAbud7miNWJ1WwEVf8=
 github.com/fergusstrange/embedded-postgres v1.10.0 h1:YnwF6xAQYmKLAXXrrRx4rHDLih47YJwVPvg8jeKfdNg=
 github.com/fergusstrange/embedded-postgres v1.10.0/go.mod h1:a008U8/Rws5FtIOTGYDYa7beVWsT3qVKyqExqYYjL+c=
 github.com/getsentry/raven-go v0.2.0 h1:no+xWJRb5ZI7eE8TWgIq1jLulQiIoLG0IfYxv5JYMGs=
@@ -103,9 +101,8 @@ github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QD
 github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
 github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
 github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
+github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=
 github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
-github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg=
-github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
 github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
 github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM=
 github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
@@ -433,7 +430,7 @@ golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE=
 golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
 golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
 golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
-golang.org/x/oauth2 v0.7.0 h1:qe6s0zUXlPX80/dITx3440hWZ7GwMwgDDyrSGTPJG/g=
+golang.org/x/oauth2 v0.4.0 h1:NF0gk8LVPg1Ml7SSbGyySuoxdsXitj7TvgvuRxIMc/M=
 golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@@ -520,8 +517,8 @@ google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98
 google.golang.org/genproto v0.0.0-20200423170343-7949de9c1215/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
 google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
 google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
-google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1 h1:KpwkzHKEF7B9Zxg18WzOa7djJ+Ha5DzthMyZYQfEn2A=
-google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1/go.mod h1:nKE/iIaLqn2bQwXBg8f1g2Ylh6r5MN5CmZvuzZCgsCU=
+google.golang.org/genproto v0.0.0-20230110181048-76db0878b65f h1:BWUVssLB0HVOSY78gIdvk1dTVYtT1y8SBWtPYuTJ/6w=
+google.golang.org/genproto v0.0.0-20230110181048-76db0878b65f/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM=
 google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
 google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
 google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
@@ -532,8 +529,8 @@ google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAG
 google.golang.org/grpc v1.37.1/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM=
 google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34=
 google.golang.org/grpc v1.41.0/go.mod h1:U3l9uK9J0sini8mHphKoXyaqDA/8VyGnDee1zzIUK6k=
-google.golang.org/grpc v1.56.3 h1:8I4C0Yq1EjstUzUJzpcRVbuYA2mODtEmpWiQoN/b2nc=
-google.golang.org/grpc v1.56.3/go.mod h1:I9bI3vqKfayGqPUAwGdOSu7kt6oIJLixfffKrpXqQ9s=
+google.golang.org/grpc v1.53.0 h1:LAv2ds7cmFV/XTS3XG1NneeENYrXGmorPxsBbptIjNc=
+google.golang.org/grpc v1.53.0/go.mod h1:OnIrk0ipVdj4N5d9IUoFUx72/VlD7+jUsHwZgwSMQpw=
 google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
 google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
 google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
diff --git a/lnrpc/chainrpc/chain_server.go b/lnrpc/chainrpc/chain_server.go
index 00a30c07c..89f480b8b 100644
--- a/lnrpc/chainrpc/chain_server.go
+++ b/lnrpc/chainrpc/chain_server.go
@@ -46,10 +46,6 @@ var (
 			Entity: "onchain",
 			Action: "read",
 		}},
-		"/chainrpc.ChainKit/GetBlockHeader": {{
-			Entity: "onchain",
-			Action: "read",
-		}},
 		"/chainrpc.ChainKit/GetBestBlock": {{
 			Entity: "onchain",
 			Action: "read",
@@ -297,31 +293,6 @@ func (s *Server) GetBlock(_ context.Context,
 	return &GetBlockResponse{RawBlock: rawBlock}, nil
 }
 
-// GetBlockHeader returns a block header given the corresponding block hash.
-func (s *Server) GetBlockHeader(_ context.Context,
-	in *GetBlockHeaderRequest) (*GetBlockHeaderResponse, error) {
-
-	// We'll start by reconstructing the RPC request into what the
-	// underlying chain functionality expects.
-	var blockHash chainhash.Hash
-	copy(blockHash[:], in.BlockHash)
-
-	blockHeader, err := s.cfg.Chain.GetBlockHeader(&blockHash)
-	if err != nil {
-		return nil, err
-	}
-
-	// Serialize block header for RPC response.
-	var headerBuf bytes.Buffer
-	err = blockHeader.Serialize(&headerBuf)
-	if err != nil {
-		return nil, err
-	}
-	rawHeader := headerBuf.Bytes()
-
-	return &GetBlockHeaderResponse{RawBlockHeader: rawHeader}, nil
-}
-
 // GetBestBlock returns the latest block hash and current height of the valid
 // most-work chain.
 func (s *Server) GetBestBlock(_ context.Context,
diff --git a/lnrpc/chainrpc/chainkit.pb.go b/lnrpc/chainrpc/chainkit.pb.go
index dc478f71f..5dd261fd5 100644
--- a/lnrpc/chainrpc/chainkit.pb.go
+++ b/lnrpc/chainrpc/chainkit.pb.go
@@ -118,102 +118,6 @@ func (x *GetBlockResponse) GetRawBlock() []byte {
 	return nil
 }
 
-type GetBlockHeaderRequest struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
-	unknownFields protoimpl.UnknownFields
-
-	// The hash of the block with the requested header.
-	BlockHash []byte `protobuf:"bytes,1,opt,name=block_hash,json=blockHash,proto3" json:"block_hash,omitempty"`
-}
-
-func (x *GetBlockHeaderRequest) Reset() {
-	*x = GetBlockHeaderRequest{}
-	if protoimpl.UnsafeEnabled {
-		mi := &file_chainrpc_chainkit_proto_msgTypes[2]
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		ms.StoreMessageInfo(mi)
-	}
-}
-
-func (x *GetBlockHeaderRequest) String() string {
-	return protoimpl.X.MessageStringOf(x)
-}
-
-func (*GetBlockHeaderRequest) ProtoMessage() {}
-
-func (x *GetBlockHeaderRequest) ProtoReflect() protoreflect.Message {
-	mi := &file_chainrpc_chainkit_proto_msgTypes[2]
-	if protoimpl.UnsafeEnabled && x != nil {
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		if ms.LoadMessageInfo() == nil {
-			ms.StoreMessageInfo(mi)
-		}
-		return ms
-	}
-	return mi.MessageOf(x)
-}
-
-// Deprecated: Use GetBlockHeaderRequest.ProtoReflect.Descriptor instead.
-func (*GetBlockHeaderRequest) Descriptor() ([]byte, []int) {
-	return file_chainrpc_chainkit_proto_rawDescGZIP(), []int{2}
-}
-
-func (x *GetBlockHeaderRequest) GetBlockHash() []byte {
-	if x != nil {
-		return x.BlockHash
-	}
-	return nil
-}
-
-type GetBlockHeaderResponse struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
-	unknownFields protoimpl.UnknownFields
-
-	// The header of the block with the requested hash.
-	RawBlockHeader []byte `protobuf:"bytes,1,opt,name=raw_block_header,json=rawBlockHeader,proto3" json:"raw_block_header,omitempty"`
-}
-
-func (x *GetBlockHeaderResponse) Reset() {
-	*x = GetBlockHeaderResponse{}
-	if protoimpl.UnsafeEnabled {
-		mi := &file_chainrpc_chainkit_proto_msgTypes[3]
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		ms.StoreMessageInfo(mi)
-	}
-}
-
-func (x *GetBlockHeaderResponse) String() string {
-	return protoimpl.X.MessageStringOf(x)
-}
-
-func (*GetBlockHeaderResponse) ProtoMessage() {}
-
-func (x *GetBlockHeaderResponse) ProtoReflect() protoreflect.Message {
-	mi := &file_chainrpc_chainkit_proto_msgTypes[3]
-	if protoimpl.UnsafeEnabled && x != nil {
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		if ms.LoadMessageInfo() == nil {
-			ms.StoreMessageInfo(mi)
-		}
-		return ms
-	}
-	return mi.MessageOf(x)
-}
-
-// Deprecated: Use GetBlockHeaderResponse.ProtoReflect.Descriptor instead.
-func (*GetBlockHeaderResponse) Descriptor() ([]byte, []int) {
-	return file_chainrpc_chainkit_proto_rawDescGZIP(), []int{3}
-}
-
-func (x *GetBlockHeaderResponse) GetRawBlockHeader() []byte {
-	if x != nil {
-		return x.RawBlockHeader
-	}
-	return nil
-}
-
 type GetBestBlockRequest struct {
 	state         protoimpl.MessageState
 	sizeCache     protoimpl.SizeCache
@@ -223,7 +127,7 @@ type GetBestBlockRequest struct {
 func (x *GetBestBlockRequest) Reset() {
 	*x = GetBestBlockRequest{}
 	if protoimpl.UnsafeEnabled {
-		mi := &file_chainrpc_chainkit_proto_msgTypes[4]
+		mi := &file_chainrpc_chainkit_proto_msgTypes[2]
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		ms.StoreMessageInfo(mi)
 	}
@@ -236,7 +140,7 @@ func (x *GetBestBlockRequest) String() string {
 func (*GetBestBlockRequest) ProtoMessage() {}
 
 func (x *GetBestBlockRequest) ProtoReflect() protoreflect.Message {
-	mi := &file_chainrpc_chainkit_proto_msgTypes[4]
+	mi := &file_chainrpc_chainkit_proto_msgTypes[2]
 	if protoimpl.UnsafeEnabled && x != nil {
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		if ms.LoadMessageInfo() == nil {
@@ -249,7 +153,7 @@ func (x *GetBestBlockRequest) ProtoReflect() protoreflect.Message {
 
 // Deprecated: Use GetBestBlockRequest.ProtoReflect.Descriptor instead.
 func (*GetBestBlockRequest) Descriptor() ([]byte, []int) {
-	return file_chainrpc_chainkit_proto_rawDescGZIP(), []int{4}
+	return file_chainrpc_chainkit_proto_rawDescGZIP(), []int{2}
 }
 
 type GetBestBlockResponse struct {
@@ -266,7 +170,7 @@ type GetBestBlockResponse struct {
 func (x *GetBestBlockResponse) Reset() {
 	*x = GetBestBlockResponse{}
 	if protoimpl.UnsafeEnabled {
-		mi := &file_chainrpc_chainkit_proto_msgTypes[5]
+		mi := &file_chainrpc_chainkit_proto_msgTypes[3]
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		ms.StoreMessageInfo(mi)
 	}
@@ -279,7 +183,7 @@ func (x *GetBestBlockResponse) String() string {
 func (*GetBestBlockResponse) ProtoMessage() {}
 
 func (x *GetBestBlockResponse) ProtoReflect() protoreflect.Message {
-	mi := &file_chainrpc_chainkit_proto_msgTypes[5]
+	mi := &file_chainrpc_chainkit_proto_msgTypes[3]
 	if protoimpl.UnsafeEnabled && x != nil {
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		if ms.LoadMessageInfo() == nil {
@@ -292,7 +196,7 @@ func (x *GetBestBlockResponse) ProtoReflect() protoreflect.Message {
 
 // Deprecated: Use GetBestBlockResponse.ProtoReflect.Descriptor instead.
 func (*GetBestBlockResponse) Descriptor() ([]byte, []int) {
-	return file_chainrpc_chainkit_proto_rawDescGZIP(), []int{5}
+	return file_chainrpc_chainkit_proto_rawDescGZIP(), []int{3}
 }
 
 func (x *GetBestBlockResponse) GetBlockHash() []byte {
@@ -321,7 +225,7 @@ type GetBlockHashRequest struct {
 func (x *GetBlockHashRequest) Reset() {
 	*x = GetBlockHashRequest{}
 	if protoimpl.UnsafeEnabled {
-		mi := &file_chainrpc_chainkit_proto_msgTypes[6]
+		mi := &file_chainrpc_chainkit_proto_msgTypes[4]
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		ms.StoreMessageInfo(mi)
 	}
@@ -334,7 +238,7 @@ func (x *GetBlockHashRequest) String() string {
 func (*GetBlockHashRequest) ProtoMessage() {}
 
 func (x *GetBlockHashRequest) ProtoReflect() protoreflect.Message {
-	mi := &file_chainrpc_chainkit_proto_msgTypes[6]
+	mi := &file_chainrpc_chainkit_proto_msgTypes[4]
 	if protoimpl.UnsafeEnabled && x != nil {
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		if ms.LoadMessageInfo() == nil {
@@ -347,7 +251,7 @@ func (x *GetBlockHashRequest) ProtoReflect() protoreflect.Message {
 
 // Deprecated: Use GetBlockHashRequest.ProtoReflect.Descriptor instead.
 func (*GetBlockHashRequest) Descriptor() ([]byte, []int) {
-	return file_chainrpc_chainkit_proto_rawDescGZIP(), []int{6}
+	return file_chainrpc_chainkit_proto_rawDescGZIP(), []int{4}
 }
 
 func (x *GetBlockHashRequest) GetBlockHeight() int64 {
@@ -369,7 +273,7 @@ type GetBlockHashResponse struct {
 func (x *GetBlockHashResponse) Reset() {
 	*x = GetBlockHashResponse{}
 	if protoimpl.UnsafeEnabled {
-		mi := &file_chainrpc_chainkit_proto_msgTypes[7]
+		mi := &file_chainrpc_chainkit_proto_msgTypes[5]
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		ms.StoreMessageInfo(mi)
 	}
@@ -382,7 +286,7 @@ func (x *GetBlockHashResponse) String() string {
 func (*GetBlockHashResponse) ProtoMessage() {}
 
 func (x *GetBlockHashResponse) ProtoReflect() protoreflect.Message {
-	mi := &file_chainrpc_chainkit_proto_msgTypes[7]
+	mi := &file_chainrpc_chainkit_proto_msgTypes[5]
 	if protoimpl.UnsafeEnabled && x != nil {
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		if ms.LoadMessageInfo() == nil {
@@ -395,7 +299,7 @@ func (x *GetBlockHashResponse) ProtoReflect() protoreflect.Message {
 
 // Deprecated: Use GetBlockHashResponse.ProtoReflect.Descriptor instead.
 func (*GetBlockHashResponse) Descriptor() ([]byte, []int) {
-	return file_chainrpc_chainkit_proto_rawDescGZIP(), []int{7}
+	return file_chainrpc_chainkit_proto_rawDescGZIP(), []int{5}
 }
 
 func (x *GetBlockHashResponse) GetBlockHash() []byte {
@@ -416,53 +320,39 @@ var file_chainrpc_chainkit_proto_rawDesc = []byte{
 	0x6b, 0x48, 0x61, 0x73, 0x68, 0x22, 0x2f, 0x0a, 0x10, 0x47, 0x65, 0x74, 0x42, 0x6c, 0x6f, 0x63,
 	0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x72, 0x61, 0x77,
 	0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x08, 0x72, 0x61,
-	0x77, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x22, 0x36, 0x0a, 0x15, 0x47, 0x65, 0x74, 0x42, 0x6c, 0x6f,
-	0x63, 0x6b, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12,
-	0x1d, 0x0a, 0x0a, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0x01, 0x20,
-	0x01, 0x28, 0x0c, 0x52, 0x09, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x61, 0x73, 0x68, 0x22, 0x42,
-	0x0a, 0x16, 0x47, 0x65, 0x74, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72,
-	0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x28, 0x0a, 0x10, 0x72, 0x61, 0x77, 0x5f,
-	0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01,
-	0x28, 0x0c, 0x52, 0x0e, 0x72, 0x61, 0x77, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x65, 0x61, 0x64,
-	0x65, 0x72, 0x22, 0x15, 0x0a, 0x13, 0x47, 0x65, 0x74, 0x42, 0x65, 0x73, 0x74, 0x42, 0x6c, 0x6f,
-	0x63, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x58, 0x0a, 0x14, 0x47, 0x65, 0x74,
-	0x42, 0x65, 0x73, 0x74, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
-	0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18,
-	0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x61, 0x73, 0x68,
-	0x12, 0x21, 0x0a, 0x0c, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74,
-	0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0b, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x65, 0x69,
-	0x67, 0x68, 0x74, 0x22, 0x38, 0x0a, 0x13, 0x47, 0x65, 0x74, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x48,
-	0x61, 0x73, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x21, 0x0a, 0x0c, 0x62, 0x6c,
-	0x6f, 0x63, 0x6b, 0x5f, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03,
-	0x52, 0x0b, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x65, 0x69, 0x67, 0x68, 0x74, 0x22, 0x35, 0x0a,
-	0x14, 0x47, 0x65, 0x74, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x61, 0x73, 0x68, 0x52, 0x65, 0x73,
+	0x77, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x22, 0x15, 0x0a, 0x13, 0x47, 0x65, 0x74, 0x42, 0x65, 0x73,
+	0x74, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x58, 0x0a,
+	0x14, 0x47, 0x65, 0x74, 0x42, 0x65, 0x73, 0x74, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x65, 0x73,
 	0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x68,
 	0x61, 0x73, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x62, 0x6c, 0x6f, 0x63, 0x6b,
-	0x48, 0x61, 0x73, 0x68, 0x32, 0xc0, 0x02, 0x0a, 0x08, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4b, 0x69,
-	0x74, 0x12, 0x41, 0x0a, 0x08, 0x47, 0x65, 0x74, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x19, 0x2e,
-	0x63, 0x68, 0x61, 0x69, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x42, 0x6c, 0x6f, 0x63,
-	0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1a, 0x2e, 0x63, 0x68, 0x61, 0x69, 0x6e,
-	0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x65, 0x73, 0x70,
-	0x6f, 0x6e, 0x73, 0x65, 0x12, 0x53, 0x0a, 0x0e, 0x47, 0x65, 0x74, 0x42, 0x6c, 0x6f, 0x63, 0x6b,
-	0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, 0x1f, 0x2e, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x72, 0x70,
-	0x63, 0x2e, 0x47, 0x65, 0x74, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72,
-	0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x72,
-	0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x65, 0x61, 0x64, 0x65,
-	0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4d, 0x0a, 0x0c, 0x47, 0x65, 0x74,
-	0x42, 0x65, 0x73, 0x74, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x1d, 0x2e, 0x63, 0x68, 0x61, 0x69,
-	0x6e, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x42, 0x65, 0x73, 0x74, 0x42, 0x6c, 0x6f, 0x63,
-	0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x63, 0x68, 0x61, 0x69, 0x6e,
-	0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x42, 0x65, 0x73, 0x74, 0x42, 0x6c, 0x6f, 0x63, 0x6b,
+	0x48, 0x61, 0x73, 0x68, 0x12, 0x21, 0x0a, 0x0c, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x68, 0x65,
+	0x69, 0x67, 0x68, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0b, 0x62, 0x6c, 0x6f, 0x63,
+	0x6b, 0x48, 0x65, 0x69, 0x67, 0x68, 0x74, 0x22, 0x38, 0x0a, 0x13, 0x47, 0x65, 0x74, 0x42, 0x6c,
+	0x6f, 0x63, 0x6b, 0x48, 0x61, 0x73, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x21,
+	0x0a, 0x0c, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x18, 0x01,
+	0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x65, 0x69, 0x67, 0x68,
+	0x74, 0x22, 0x35, 0x0a, 0x14, 0x47, 0x65, 0x74, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x61, 0x73,
+	0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x62, 0x6c, 0x6f,
+	0x63, 0x6b, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x62,
+	0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x61, 0x73, 0x68, 0x32, 0xeb, 0x01, 0x0a, 0x08, 0x43, 0x68, 0x61,
+	0x69, 0x6e, 0x4b, 0x69, 0x74, 0x12, 0x41, 0x0a, 0x08, 0x47, 0x65, 0x74, 0x42, 0x6c, 0x6f, 0x63,
+	0x6b, 0x12, 0x19, 0x2e, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74,
+	0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1a, 0x2e, 0x63,
+	0x68, 0x61, 0x69, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x42, 0x6c, 0x6f, 0x63, 0x6b,
 	0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4d, 0x0a, 0x0c, 0x47, 0x65, 0x74, 0x42,
-	0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x61, 0x73, 0x68, 0x12, 0x1d, 0x2e, 0x63, 0x68, 0x61, 0x69, 0x6e,
-	0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x61, 0x73, 0x68,
+	0x65, 0x73, 0x74, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x1d, 0x2e, 0x63, 0x68, 0x61, 0x69, 0x6e,
+	0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x42, 0x65, 0x73, 0x74, 0x42, 0x6c, 0x6f, 0x63, 0x6b,
 	0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x72,
+	0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x42, 0x65, 0x73, 0x74, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52,
+	0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4d, 0x0a, 0x0c, 0x47, 0x65, 0x74, 0x42, 0x6c,
+	0x6f, 0x63, 0x6b, 0x48, 0x61, 0x73, 0x68, 0x12, 0x1d, 0x2e, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x72,
 	0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x61, 0x73, 0x68, 0x52,
-	0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x30, 0x5a, 0x2e, 0x67, 0x69, 0x74, 0x68, 0x75,
-	0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x6e, 0x69, 0x6e, 0x67, 0x6e,
-	0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x2f, 0x6c, 0x6e, 0x64, 0x2f, 0x6c, 0x6e, 0x72, 0x70, 0x63,
-	0x2f, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x72, 0x70, 0x63, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f,
-	0x33,
+	0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x72, 0x70,
+	0x63, 0x2e, 0x47, 0x65, 0x74, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x61, 0x73, 0x68, 0x52, 0x65,
+	0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x30, 0x5a, 0x2e, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62,
+	0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x6e, 0x69, 0x6e, 0x67, 0x6e, 0x65,
+	0x74, 0x77, 0x6f, 0x72, 0x6b, 0x2f, 0x6c, 0x6e, 0x64, 0x2f, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2f,
+	0x63, 0x68, 0x61, 0x69, 0x6e, 0x72, 0x70, 0x63, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
 }
 
 var (
@@ -477,28 +367,24 @@ func file_chainrpc_chainkit_proto_rawDescGZIP() []byte {
 	return file_chainrpc_chainkit_proto_rawDescData
 }
 
-var file_chainrpc_chainkit_proto_msgTypes = make([]protoimpl.MessageInfo, 8)
+var file_chainrpc_chainkit_proto_msgTypes = make([]protoimpl.MessageInfo, 6)
 var file_chainrpc_chainkit_proto_goTypes = []interface{}{
-	(*GetBlockRequest)(nil),        // 0: chainrpc.GetBlockRequest
-	(*GetBlockResponse)(nil),       // 1: chainrpc.GetBlockResponse
-	(*GetBlockHeaderRequest)(nil),  // 2: chainrpc.GetBlockHeaderRequest
-	(*GetBlockHeaderResponse)(nil), // 3: chainrpc.GetBlockHeaderResponse
-	(*GetBestBlockRequest)(nil),    // 4: chainrpc.GetBestBlockRequest
-	(*GetBestBlockResponse)(nil),   // 5: chainrpc.GetBestBlockResponse
-	(*GetBlockHashRequest)(nil),    // 6: chainrpc.GetBlockHashRequest
-	(*GetBlockHashResponse)(nil),   // 7: chainrpc.GetBlockHashResponse
+	(*GetBlockRequest)(nil),      // 0: chainrpc.GetBlockRequest
+	(*GetBlockResponse)(nil),     // 1: chainrpc.GetBlockResponse
+	(*GetBestBlockRequest)(nil),  // 2: chainrpc.GetBestBlockRequest
+	(*GetBestBlockResponse)(nil), // 3: chainrpc.GetBestBlockResponse
+	(*GetBlockHashRequest)(nil),  // 4: chainrpc.GetBlockHashRequest
+	(*GetBlockHashResponse)(nil), // 5: chainrpc.GetBlockHashResponse
 }
 var file_chainrpc_chainkit_proto_depIdxs = []int32{
 	0, // 0: chainrpc.ChainKit.GetBlock:input_type -> chainrpc.GetBlockRequest
-	2, // 1: chainrpc.ChainKit.GetBlockHeader:input_type -> chainrpc.GetBlockHeaderRequest
-	4, // 2: chainrpc.ChainKit.GetBestBlock:input_type -> chainrpc.GetBestBlockRequest
-	6, // 3: chainrpc.ChainKit.GetBlockHash:input_type -> chainrpc.GetBlockHashRequest
-	1, // 4: chainrpc.ChainKit.GetBlock:output_type -> chainrpc.GetBlockResponse
-	3, // 5: chainrpc.ChainKit.GetBlockHeader:output_type -> chainrpc.GetBlockHeaderResponse
-	5, // 6: chainrpc.ChainKit.GetBestBlock:output_type -> chainrpc.GetBestBlockResponse
-	7, // 7: chainrpc.ChainKit.GetBlockHash:output_type -> chainrpc.GetBlockHashResponse
-	4, // [4:8] is the sub-list for method output_type
-	0, // [0:4] is the sub-list for method input_type
+	2, // 1: chainrpc.ChainKit.GetBestBlock:input_type -> chainrpc.GetBestBlockRequest
+	4, // 2: chainrpc.ChainKit.GetBlockHash:input_type -> chainrpc.GetBlockHashRequest
+	1, // 3: chainrpc.ChainKit.GetBlock:output_type -> chainrpc.GetBlockResponse
+	3, // 4: chainrpc.ChainKit.GetBestBlock:output_type -> chainrpc.GetBestBlockResponse
+	5, // 5: chainrpc.ChainKit.GetBlockHash:output_type -> chainrpc.GetBlockHashResponse
+	3, // [3:6] is the sub-list for method output_type
+	0, // [0:3] is the sub-list for method input_type
 	0, // [0:0] is the sub-list for extension type_name
 	0, // [0:0] is the sub-list for extension extendee
 	0, // [0:0] is the sub-list for field type_name
@@ -535,30 +421,6 @@ func file_chainrpc_chainkit_proto_init() {
 			}
 		}
 		file_chainrpc_chainkit_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
-			switch v := v.(*GetBlockHeaderRequest); i {
-			case 0:
-				return &v.state
-			case 1:
-				return &v.sizeCache
-			case 2:
-				return &v.unknownFields
-			default:
-				return nil
-			}
-		}
-		file_chainrpc_chainkit_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} {
-			switch v := v.(*GetBlockHeaderResponse); i {
-			case 0:
-				return &v.state
-			case 1:
-				return &v.sizeCache
-			case 2:
-				return &v.unknownFields
-			default:
-				return nil
-			}
-		}
-		file_chainrpc_chainkit_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} {
 			switch v := v.(*GetBestBlockRequest); i {
 			case 0:
 				return &v.state
@@ -570,7 +432,7 @@ func file_chainrpc_chainkit_proto_init() {
 				return nil
 			}
 		}
-		file_chainrpc_chainkit_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} {
+		file_chainrpc_chainkit_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} {
 			switch v := v.(*GetBestBlockResponse); i {
 			case 0:
 				return &v.state
@@ -582,7 +444,7 @@ func file_chainrpc_chainkit_proto_init() {
 				return nil
 			}
 		}
-		file_chainrpc_chainkit_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} {
+		file_chainrpc_chainkit_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} {
 			switch v := v.(*GetBlockHashRequest); i {
 			case 0:
 				return &v.state
@@ -594,7 +456,7 @@ func file_chainrpc_chainkit_proto_init() {
 				return nil
 			}
 		}
-		file_chainrpc_chainkit_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} {
+		file_chainrpc_chainkit_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} {
 			switch v := v.(*GetBlockHashResponse); i {
 			case 0:
 				return &v.state
@@ -613,7 +475,7 @@ func file_chainrpc_chainkit_proto_init() {
 			GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
 			RawDescriptor: file_chainrpc_chainkit_proto_rawDesc,
 			NumEnums:      0,
-			NumMessages:   8,
+			NumMessages:   6,
 			NumExtensions: 0,
 			NumServices:   1,
 		},
diff --git a/lnrpc/chainrpc/chainkit.pb.gw.go b/lnrpc/chainrpc/chainkit.pb.gw.go
index 665f63295..d49ed54ff 100644
--- a/lnrpc/chainrpc/chainkit.pb.gw.go
+++ b/lnrpc/chainrpc/chainkit.pb.gw.go
@@ -67,42 +67,6 @@ func local_request_ChainKit_GetBlock_0(ctx context.Context, marshaler runtime.Ma
 
 }
 
-var (
-	filter_ChainKit_GetBlockHeader_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)}
-)
-
-func request_ChainKit_GetBlockHeader_0(ctx context.Context, marshaler runtime.Marshaler, client ChainKitClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
-	var protoReq GetBlockHeaderRequest
-	var metadata runtime.ServerMetadata
-
-	if err := req.ParseForm(); err != nil {
-		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
-	}
-	if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_ChainKit_GetBlockHeader_0); err != nil {
-		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
-	}
-
-	msg, err := client.GetBlockHeader(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
-	return msg, metadata, err
-
-}
-
-func local_request_ChainKit_GetBlockHeader_0(ctx context.Context, marshaler runtime.Marshaler, server ChainKitServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
-	var protoReq GetBlockHeaderRequest
-	var metadata runtime.ServerMetadata
-
-	if err := req.ParseForm(); err != nil {
-		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
-	}
-	if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_ChainKit_GetBlockHeader_0); err != nil {
-		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
-	}
-
-	msg, err := server.GetBlockHeader(ctx, &protoReq)
-	return msg, metadata, err
-
-}
-
 func request_ChainKit_GetBestBlock_0(ctx context.Context, marshaler runtime.Marshaler, client ChainKitClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
 	var protoReq GetBestBlockRequest
 	var metadata runtime.ServerMetadata
@@ -186,29 +150,6 @@ func RegisterChainKitHandlerServer(ctx context.Context, mux *runtime.ServeMux, s
 
 	})
 
-	mux.Handle("GET", pattern_ChainKit_GetBlockHeader_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
-		ctx, cancel := context.WithCancel(req.Context())
-		defer cancel()
-		var stream runtime.ServerTransportStream
-		ctx = grpc.NewContextWithServerTransportStream(ctx, &stream)
-		inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
-		rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/chainrpc.ChainKit/GetBlockHeader", runtime.WithHTTPPathPattern("/v2/chainkit/blockheader"))
-		if err != nil {
-			runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
-			return
-		}
-		resp, md, err := local_request_ChainKit_GetBlockHeader_0(rctx, inboundMarshaler, server, req, pathParams)
-		md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer())
-		ctx = runtime.NewServerMetadataContext(ctx, md)
-		if err != nil {
-			runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
-			return
-		}
-
-		forward_ChainKit_GetBlockHeader_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
-
-	})
-
 	mux.Handle("GET", pattern_ChainKit_GetBestBlock_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
 		ctx, cancel := context.WithCancel(req.Context())
 		defer cancel()
@@ -316,26 +257,6 @@ func RegisterChainKitHandlerClient(ctx context.Context, mux *runtime.ServeMux, c
 
 	})
 
-	mux.Handle("GET", pattern_ChainKit_GetBlockHeader_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
-		ctx, cancel := context.WithCancel(req.Context())
-		defer cancel()
-		inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
-		rctx, err := runtime.AnnotateContext(ctx, mux, req, "/chainrpc.ChainKit/GetBlockHeader", runtime.WithHTTPPathPattern("/v2/chainkit/blockheader"))
-		if err != nil {
-			runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
-			return
-		}
-		resp, md, err := request_ChainKit_GetBlockHeader_0(rctx, inboundMarshaler, client, req, pathParams)
-		ctx = runtime.NewServerMetadataContext(ctx, md)
-		if err != nil {
-			runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
-			return
-		}
-
-		forward_ChainKit_GetBlockHeader_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
-
-	})
-
 	mux.Handle("GET", pattern_ChainKit_GetBestBlock_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
 		ctx, cancel := context.WithCancel(req.Context())
 		defer cancel()
@@ -382,8 +303,6 @@ func RegisterChainKitHandlerClient(ctx context.Context, mux *runtime.ServeMux, c
 var (
 	pattern_ChainKit_GetBlock_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v2", "chainkit", "block"}, ""))
 
-	pattern_ChainKit_GetBlockHeader_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v2", "chainkit", "blockheader"}, ""))
-
 	pattern_ChainKit_GetBestBlock_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v2", "chainkit", "bestblock"}, ""))
 
 	pattern_ChainKit_GetBlockHash_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v2", "chainkit", "blockhash"}, ""))
@@ -392,8 +311,6 @@ var (
 var (
 	forward_ChainKit_GetBlock_0 = runtime.ForwardResponseMessage
 
-	forward_ChainKit_GetBlockHeader_0 = runtime.ForwardResponseMessage
-
 	forward_ChainKit_GetBestBlock_0 = runtime.ForwardResponseMessage
 
 	forward_ChainKit_GetBlockHash_0 = runtime.ForwardResponseMessage
diff --git a/lnrpc/chainrpc/chainkit.pb.json.go b/lnrpc/chainrpc/chainkit.pb.json.go
index 8979b593c..e05648a2f 100644
--- a/lnrpc/chainrpc/chainkit.pb.json.go
+++ b/lnrpc/chainrpc/chainkit.pb.json.go
@@ -46,31 +46,6 @@ func RegisterChainKitJSONCallbacks(registry map[string]func(ctx context.Context,
 		callback(string(respBytes), nil)
 	}
 
-	registry["chainrpc.ChainKit.GetBlockHeader"] = func(ctx context.Context,
-		conn *grpc.ClientConn, reqJSON string, callback func(string, error)) {
-
-		req := &GetBlockHeaderRequest{}
-		err := marshaler.Unmarshal([]byte(reqJSON), req)
-		if err != nil {
-			callback("", err)
-			return
-		}
-
-		client := NewChainKitClient(conn)
-		resp, err := client.GetBlockHeader(ctx, req)
-		if err != nil {
-			callback("", err)
-			return
-		}
-
-		respBytes, err := marshaler.Marshal(resp)
-		if err != nil {
-			callback("", err)
-			return
-		}
-		callback(string(respBytes), nil)
-	}
-
 	registry["chainrpc.ChainKit.GetBestBlock"] = func(ctx context.Context,
 		conn *grpc.ClientConn, reqJSON string, callback func(string, error)) {
 
diff --git a/lnrpc/chainrpc/chainkit.proto b/lnrpc/chainrpc/chainkit.proto
index 150e0563d..8db7c52d2 100644
--- a/lnrpc/chainrpc/chainkit.proto
+++ b/lnrpc/chainrpc/chainkit.proto
@@ -12,11 +12,6 @@ service ChainKit {
     */
     rpc GetBlock (GetBlockRequest) returns (GetBlockResponse);
 
-    /* lncli: `chain getblockheader`
-    GetBlockHeader returns a block header with a particular block hash.
-    */
-    rpc GetBlockHeader (GetBlockHeaderRequest) returns (GetBlockHeaderResponse);
-
     /* lncli: `chain getbestblock`
     GetBestBlock returns the block hash and current height from the valid
     most-work chain.
@@ -42,16 +37,6 @@ message GetBlockResponse {
     bytes raw_block = 1;
 }
 
-message GetBlockHeaderRequest {
-    // The hash of the block with the requested header.
-    bytes block_hash = 1;
-}
-
-message GetBlockHeaderResponse {
-    // The header of the block with the requested hash.
-    bytes raw_block_header = 1;
-}
-
 message GetBestBlockRequest {
 }
 
diff --git a/lnrpc/chainrpc/chainkit.swagger.json b/lnrpc/chainrpc/chainkit.swagger.json
index c3cbeb6df..c5bae06c0 100644
--- a/lnrpc/chainrpc/chainkit.swagger.json
+++ b/lnrpc/chainrpc/chainkit.swagger.json
@@ -104,39 +104,6 @@
           "ChainKit"
         ]
       }
-    },
-    "/v2/chainkit/blockheader": {
-      "get": {
-        "summary": "lncli: `chain getblockheader`\nGetBlockHeader returns a block header with a particular block hash.",
-        "operationId": "ChainKit_GetBlockHeader",
-        "responses": {
-          "200": {
-            "description": "A successful response.",
-            "schema": {
-              "$ref": "#/definitions/chainrpcGetBlockHeaderResponse"
-            }
-          },
-          "default": {
-            "description": "An unexpected error response.",
-            "schema": {
-              "$ref": "#/definitions/rpcStatus"
-            }
-          }
-        },
-        "parameters": [
-          {
-            "name": "block_hash",
-            "description": "The hash of the block with the requested header.",
-            "in": "query",
-            "required": false,
-            "type": "string",
-            "format": "byte"
-          }
-        ],
-        "tags": [
-          "ChainKit"
-        ]
-      }
     }
   },
   "definitions": {
@@ -165,16 +132,6 @@
         }
       }
     },
-    "chainrpcGetBlockHeaderResponse": {
-      "type": "object",
-      "properties": {
-        "raw_block_header": {
-          "type": "string",
-          "format": "byte",
-          "description": "The header of the block with the requested hash."
-        }
-      }
-    },
     "chainrpcGetBlockResponse": {
       "type": "object",
       "properties": {
diff --git a/lnrpc/chainrpc/chainkit.yaml b/lnrpc/chainrpc/chainkit.yaml
index 2241233c8..815dfc5a7 100644
--- a/lnrpc/chainrpc/chainkit.yaml
+++ b/lnrpc/chainrpc/chainkit.yaml
@@ -5,8 +5,6 @@ http:
   rules:
     - selector: chainrpc.ChainKit.GetBlock
       get: "/v2/chainkit/block"
-    - selector: chainrpc.ChainKit.GetBlockHeader
-      get: "/v2/chainkit/blockheader"
     - selector: chainrpc.ChainKit.GetBestBlock
       get: "/v2/chainkit/bestblock"
     - selector: chainrpc.ChainKit.GetBlockHash
diff --git a/lnrpc/chainrpc/chainkit_grpc.pb.go b/lnrpc/chainrpc/chainkit_grpc.pb.go
index c92c50477..47585f7f3 100644
--- a/lnrpc/chainrpc/chainkit_grpc.pb.go
+++ b/lnrpc/chainrpc/chainkit_grpc.pb.go
@@ -21,9 +21,6 @@ type ChainKitClient interface {
 	// lncli: `chain getblock`
 	// GetBlock returns a block given the corresponding block hash.
 	GetBlock(ctx context.Context, in *GetBlockRequest, opts ...grpc.CallOption) (*GetBlockResponse, error)
-	// lncli: `chain getblockheader`
-	// GetBlockHeader returns a block header with a particular block hash.
-	GetBlockHeader(ctx context.Context, in *GetBlockHeaderRequest, opts ...grpc.CallOption) (*GetBlockHeaderResponse, error)
 	// lncli: `chain getbestblock`
 	// GetBestBlock returns the block hash and current height from the valid
 	// most-work chain.
@@ -51,15 +48,6 @@ func (c *chainKitClient) GetBlock(ctx context.Context, in *GetBlockRequest, opts
 	return out, nil
 }
 
-func (c *chainKitClient) GetBlockHeader(ctx context.Context, in *GetBlockHeaderRequest, opts ...grpc.CallOption) (*GetBlockHeaderResponse, error) {
-	out := new(GetBlockHeaderResponse)
-	err := c.cc.Invoke(ctx, "/chainrpc.ChainKit/GetBlockHeader", in, out, opts...)
-	if err != nil {
-		return nil, err
-	}
-	return out, nil
-}
-
 func (c *chainKitClient) GetBestBlock(ctx context.Context, in *GetBestBlockRequest, opts ...grpc.CallOption) (*GetBestBlockResponse, error) {
 	out := new(GetBestBlockResponse)
 	err := c.cc.Invoke(ctx, "/chainrpc.ChainKit/GetBestBlock", in, out, opts...)
@@ -85,9 +73,6 @@ type ChainKitServer interface {
 	// lncli: `chain getblock`
 	// GetBlock returns a block given the corresponding block hash.
 	GetBlock(context.Context, *GetBlockRequest) (*GetBlockResponse, error)
-	// lncli: `chain getblockheader`
-	// GetBlockHeader returns a block header with a particular block hash.
-	GetBlockHeader(context.Context, *GetBlockHeaderRequest) (*GetBlockHeaderResponse, error)
 	// lncli: `chain getbestblock`
 	// GetBestBlock returns the block hash and current height from the valid
 	// most-work chain.
@@ -106,9 +91,6 @@ type UnimplementedChainKitServer struct {
 func (UnimplementedChainKitServer) GetBlock(context.Context, *GetBlockRequest) (*GetBlockResponse, error) {
 	return nil, status.Errorf(codes.Unimplemented, "method GetBlock not implemented")
 }
-func (UnimplementedChainKitServer) GetBlockHeader(context.Context, *GetBlockHeaderRequest) (*GetBlockHeaderResponse, error) {
-	return nil, status.Errorf(codes.Unimplemented, "method GetBlockHeader not implemented")
-}
 func (UnimplementedChainKitServer) GetBestBlock(context.Context, *GetBestBlockRequest) (*GetBestBlockResponse, error) {
 	return nil, status.Errorf(codes.Unimplemented, "method GetBestBlock not implemented")
 }
@@ -146,24 +128,6 @@ func _ChainKit_GetBlock_Handler(srv interface{}, ctx context.Context, dec func(i
 	return interceptor(ctx, in, info, handler)
 }
 
-func _ChainKit_GetBlockHeader_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
-	in := new(GetBlockHeaderRequest)
-	if err := dec(in); err != nil {
-		return nil, err
-	}
-	if interceptor == nil {
-		return srv.(ChainKitServer).GetBlockHeader(ctx, in)
-	}
-	info := &grpc.UnaryServerInfo{
-		Server:     srv,
-		FullMethod: "/chainrpc.ChainKit/GetBlockHeader",
-	}
-	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
-		return srv.(ChainKitServer).GetBlockHeader(ctx, req.(*GetBlockHeaderRequest))
-	}
-	return interceptor(ctx, in, info, handler)
-}
-
 func _ChainKit_GetBestBlock_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
 	in := new(GetBestBlockRequest)
 	if err := dec(in); err != nil {
@@ -211,10 +175,6 @@ var ChainKit_ServiceDesc = grpc.ServiceDesc{
 			MethodName: "GetBlock",
 			Handler:    _ChainKit_GetBlock_Handler,
 		},
-		{
-			MethodName: "GetBlockHeader",
-			Handler:    _ChainKit_GetBlockHeader_Handler,
-		},
 		{
 			MethodName: "GetBestBlock",
 			Handler:    _ChainKit_GetBestBlock_Handler,
diff --git a/lnwallet/btcwallet/blockchain.go b/lnwallet/btcwallet/blockchain.go
index 25b51d5e0..5cb0886f0 100644
--- a/lnwallet/btcwallet/blockchain.go
+++ b/lnwallet/btcwallet/blockchain.go
@@ -149,15 +149,6 @@ func (b *BtcWallet) GetBlock(blockHash *chainhash.Hash) (*wire.MsgBlock, error)
 	return b.chain.GetBlock(blockHash)
 }
 
-// GetBlockHeader returns a block header for the block with the given hash.
-//
-// This method is a part of the lnwallet.BlockChainIO interface.
-func (b *BtcWallet) GetBlockHeader(
-	blockHash *chainhash.Hash) (*wire.BlockHeader, error) {
-
-	return b.chain.GetBlockHeader(blockHash)
-}
-
 // GetBlockHash returns the hash of the block in the best blockchain at the
 // given height.
 //
diff --git a/lnwallet/chainfee/estimator.go b/lnwallet/chainfee/estimator.go
index 1b766fe80..824af3f11 100644
--- a/lnwallet/chainfee/estimator.go
+++ b/lnwallet/chainfee/estimator.go
@@ -35,6 +35,14 @@ const (
 	// maxFeeUpdateTimeout represents the maximum interval in which a
 	// WebAPIEstimator will request fresh fees from its API.
 	maxFeeUpdateTimeout = 20 * time.Minute
+
+	// WebAPIConnectionTimeout specifies the timeout value for connecting
+	// to the api source.
+	WebAPIConnectionTimeout = 5 * time.Second
+
+	// WebAPIResponseTimeout specifies the timeout value for receiving a
+	// fee response from the api source.
+	WebAPIResponseTimeout = 10 * time.Second
 )
 
 var (
@@ -493,15 +501,9 @@ var _ Estimator = (*BitcoindEstimator)(nil)
 // implementation of this interface in order to allow the WebAPIEstimator to
 // be fully generic in its logic.
 type WebAPIFeeSource interface {
-	// GenQueryURL generates the full query URL. The value returned by this
-	// method should be able to be used directly as a path for an HTTP GET
-	// request.
-	GenQueryURL() string
-
-	// ParseResponse attempts to parse the body of the response generated
-	// by the above query URL. Typically this will be JSON, but the
-	// specifics are left to the WebAPIFeeSource implementation.
-	ParseResponse(r io.Reader) (map[uint32]uint32, error)
+	// GetFeeMap will query the web API, parse the response and return a
+	// map of confirmation targets to sat/kw fees.
+	GetFeeMap() (map[uint32]uint32, error)
 }
 
 // SparseConfFeeSource is an implementation of the WebAPIFeeSource that utilizes
@@ -513,21 +515,12 @@ type SparseConfFeeSource struct {
 	URL string
 }
 
-// GenQueryURL generates the full query URL. The value returned by this
-// method should be able to be used directly as a path for an HTTP GET
-// request.
-//
-// NOTE: Part of the WebAPIFeeSource interface.
-func (s SparseConfFeeSource) GenQueryURL() string {
-	return s.URL
-}
-
-// ParseResponse attempts to parse the body of the response generated by the
+// parseResponse attempts to parse the body of the response generated by the
 // above query URL. Typically this will be JSON, but the specifics are left to
 // the WebAPIFeeSource implementation.
-//
-// NOTE: Part of the WebAPIFeeSource interface.
-func (s SparseConfFeeSource) ParseResponse(r io.Reader) (map[uint32]uint32, error) {
+func (s SparseConfFeeSource) parseResponse(r io.Reader) (
+	map[uint32]uint32, error) {
+
 	type jsonResp struct {
 		FeeByBlockTarget map[uint32]uint32 `json:"fee_by_block_target"`
 	}
@@ -543,6 +536,47 @@ func (s SparseConfFeeSource) ParseResponse(r io.Reader) (map[uint32]uint32, erro
 	return resp.FeeByBlockTarget, nil
 }
 
+// GetFeeMap will query the web API, parse the response and return a map of
+// confirmation targets to sat/kw fees.
+func (s SparseConfFeeSource) GetFeeMap() (map[uint32]uint32, error) {
+	// Rather than use the default http.Client, we'll make a custom one
+	// which will allow us to control how long we'll wait to read the
+	// response from the service. This way, if the service is down or
+	// overloaded, we can exit early and use our default fee.
+	netTransport := &http.Transport{
+		Dial: (&net.Dialer{
+			Timeout: WebAPIConnectionTimeout,
+		}).Dial,
+		TLSHandshakeTimeout: WebAPIConnectionTimeout,
+	}
+	netClient := &http.Client{
+		Timeout:   WebAPIResponseTimeout,
+		Transport: netTransport,
+	}
+
+	// With the client created, we'll query the API source to fetch the URL
+	// that we should use to query for the fee estimation.
+	targetURL := s.URL
+	resp, err := netClient.Get(targetURL)
+	if err != nil {
+		log.Errorf("unable to query web api for fee response: %v",
+			err)
+		return nil, err
+	}
+	defer resp.Body.Close()
+
+	// Once we've obtained the response, we'll instruct the WebAPIFeeSource
+	// to parse out the body to obtain our final result.
+	feesByBlockTarget, err := s.parseResponse(resp.Body)
+	if err != nil {
+		log.Errorf("unable to parse fee api response: %v", err)
+
+		return nil, err
+	}
+
+	return feesByBlockTarget, nil
+}
+
 // A compile-time assertion to ensure that SparseConfFeeSource implements the
 // WebAPIFeeSource interface.
 var _ WebAPIFeeSource = (*SparseConfFeeSource)(nil)
@@ -762,38 +796,11 @@ func (w *WebAPIEstimator) getCachedFee(numBlocks uint32) (uint32, error) {
 
 // updateFeeEstimates re-queries the API for fresh fees and caches them.
 func (w *WebAPIEstimator) updateFeeEstimates() {
-	// Rather than use the default http.Client, we'll make a custom one
-	// which will allow us to control how long we'll wait to read the
-	// response from the service. This way, if the service is down or
-	// overloaded, we can exit early and use our default fee.
-	netTransport := &http.Transport{
-		Dial: (&net.Dialer{
-			Timeout: 5 * time.Second,
-		}).Dial,
-		TLSHandshakeTimeout: 5 * time.Second,
-	}
-	netClient := &http.Client{
-		Timeout:   time.Second * 10,
-		Transport: netTransport,
-	}
-
-	// With the client created, we'll query the API source to fetch the URL
-	// that we should use to query for the fee estimation.
-	targetURL := w.apiSource.GenQueryURL()
-	resp, err := netClient.Get(targetURL)
-	if err != nil {
-		log.Errorf("unable to query web api for fee response: %v",
-			err)
-		return
-	}
-	defer resp.Body.Close()
-
 	// Once we've obtained the response, we'll instruct the WebAPIFeeSource
 	// to parse out the body to obtain our final result.
-	feesByBlockTarget, err := w.apiSource.ParseResponse(resp.Body)
+	feesByBlockTarget, err := w.apiSource.GetFeeMap()
 	if err != nil {
-		log.Errorf("unable to query web api for fee response: %v",
-			err)
+		log.Errorf("unable to get fee response: %v", err)
 		return
 	}
 
diff --git a/lnwallet/chainfee/mocks.go b/lnwallet/chainfee/mocks.go
new file mode 100644
index 000000000..03d40e11e
--- /dev/null
+++ b/lnwallet/chainfee/mocks.go
@@ -0,0 +1,17 @@
+package chainfee
+
+import "github.com/stretchr/testify/mock"
+
+type mockFeeSource struct {
+	mock.Mock
+}
+
+// A compile-time assertion to ensure that mockFeeSource implements the
+// WebAPIFeeSource interface.
+var _ WebAPIFeeSource = (*mockFeeSource)(nil)
+
+func (m *mockFeeSource) GetFeeMap() (map[uint32]uint32, error) {
+	args := m.Called()
+
+	return args.Get(0).(map[uint32]uint32), args.Error(1)
+}
diff --git a/lnwallet/interface.go b/lnwallet/interface.go
index e8dd72dc0..d8dc9d5b8 100644
--- a/lnwallet/interface.go
+++ b/lnwallet/interface.go
@@ -562,9 +562,6 @@ type BlockChainIO interface {
 	// GetBlock returns the block in the main chain identified by the given
 	// hash.
 	GetBlock(blockHash *chainhash.Hash) (*wire.MsgBlock, error)
-
-	// GetBlockHeader returns the block header for the given block hash.
-	GetBlockHeader(blockHash *chainhash.Hash) (*wire.BlockHeader, error)
 }
 
 // MessageSigner represents an abstract object capable of signing arbitrary
diff --git a/lnwallet/mock.go b/lnwallet/mock.go
index 6d382a58e..597be6618 100644
--- a/lnwallet/mock.go
+++ b/lnwallet/mock.go
@@ -364,9 +364,3 @@ func (*mockChainIO) GetBlock(blockHash *chainhash.Hash) (*wire.MsgBlock,
 
 	return nil, nil
 }
-
-func (*mockChainIO) GetBlockHeader(
-	blockHash *chainhash.Hash) (*wire.BlockHeader, error) {
-
-	return nil, nil
-}


Test patch:
diff --git a/contractcourt/channel_arbitrator_test.go b/contractcourt/channel_arbitrator_test.go
index 34c6122fd..1fce269fd 100644
--- a/contractcourt/channel_arbitrator_test.go
+++ b/contractcourt/channel_arbitrator_test.go
@@ -187,10 +187,6 @@ func (*mockChainIO) GetBlock(blockHash *chainhash.Hash) (*wire.MsgBlock, error)
 	return nil, nil
 }
 
-func (*mockChainIO) GetBlockHeader(*chainhash.Hash) (*wire.BlockHeader, error) {
-	return nil, nil
-}
-
 type chanArbTestCtx struct {
 	t *testing.T
 
diff --git a/itest/lnd_onchain_test.go b/itest/lnd_onchain_test.go
index 7bd97c8bd..4cfe47d37 100644
--- a/itest/lnd_onchain_test.go
+++ b/itest/lnd_onchain_test.go
@@ -26,7 +26,6 @@ func testChainKit(ht *lntest.HarnessTest) {
 	// during execution. By calling sub-test functions as seen below we
 	// avoid the need to start separate nodes.
 	testChainKitGetBlock(ht)
-	testChainKitGetBlockHeader(ht)
 	testChainKitGetBlockHash(ht)
 	testChainKitSendOutputsAnchorReserve(ht)
 }
@@ -59,49 +58,6 @@ func testChainKitGetBlock(ht *lntest.HarnessTest) {
 	require.Equal(ht, expected, actual)
 }
 
-// testChainKitGetBlockHeader ensures that given a block hash, the RPC endpoint
-// returns the correct target block header.
-func testChainKitGetBlockHeader(ht *lntest.HarnessTest) {
-	// Get best block hash.
-	bestBlockRes := ht.Alice.RPC.GetBestBlock(nil)
-
-	var (
-		bestBlockHash   chainhash.Hash
-		bestBlockHeader wire.BlockHeader
-		msgBlock        = &wire.MsgBlock{}
-	)
-	err := bestBlockHash.SetBytes(bestBlockRes.BlockHash)
-	require.NoError(ht, err)
-
-	// Retrieve the best block by hash.
-	getBlockReq := &chainrpc.GetBlockRequest{
-		BlockHash: bestBlockHash[:],
-	}
-	getBlockRes := ht.Alice.RPC.GetBlock(getBlockReq)
-
-	// Deserialize the block which was retrieved by hash.
-	blockReader := bytes.NewReader(getBlockRes.RawBlock)
-	err = msgBlock.Deserialize(blockReader)
-	require.NoError(ht, err)
-
-	// Retrieve the block header for the best block.
-	getBlockHeaderReq := &chainrpc.GetBlockHeaderRequest{
-		BlockHash: bestBlockHash[:],
-	}
-	getBlockHeaderRes := ht.Alice.RPC.GetBlockHeader(getBlockHeaderReq)
-
-	// Deserialize the block header which was retrieved by hash.
-	blockHeaderReader := bytes.NewReader(getBlockHeaderRes.RawBlockHeader)
-	err = bestBlockHeader.Deserialize(blockHeaderReader)
-	require.NoError(ht, err)
-
-	// Ensure the header of the best block is the same as retrieved block
-	// header.
-	expected := bestBlockHeader
-	actual := msgBlock.Header
-	require.Equal(ht, expected, actual)
-}
-
 // testChainKitGetBlockHash ensures that given a block height, the RPC endpoint
 // returns the correct target block hash.
 func testChainKitGetBlockHash(ht *lntest.HarnessTest) {
diff --git a/lntest/mock/chainio.go b/lntest/mock/chainio.go
index 4dd0868b2..1f07056f0 100644
--- a/lntest/mock/chainio.go
+++ b/lntest/mock/chainio.go
@@ -32,10 +32,3 @@ func (c *ChainIO) GetBlockHash(blockHeight int64) (*chainhash.Hash, error) {
 func (c *ChainIO) GetBlock(blockHash *chainhash.Hash) (*wire.MsgBlock, error) {
 	return nil, nil
 }
-
-// GetBlockHeader currently returns dummy values.
-func (c *ChainIO) GetBlockHeader(blockHash *chainhash.Hash) (*wire.BlockHeader,
-	error) {
-
-	return nil, nil
-}
diff --git a/lntest/rpc/chain_kit.go b/lntest/rpc/chain_kit.go
index 453de276a..c668b3a0f 100644
--- a/lntest/rpc/chain_kit.go
+++ b/lntest/rpc/chain_kit.go
@@ -45,24 +45,6 @@ func (h *HarnessRPC) GetBlock(
 	return resp
 }
 
-// GetBlockHeader makes an RPC call to chain kit client's GetBlockHeader and
-// asserts.
-func (h *HarnessRPC) GetBlockHeader(
-	req *chainrpc.GetBlockHeaderRequest) *chainrpc.GetBlockHeaderResponse {
-
-	if req == nil {
-		req = &chainrpc.GetBlockHeaderRequest{}
-	}
-
-	ctxt, cancel := context.WithTimeout(h.runCtx, DefaultTimeout)
-	defer cancel()
-
-	resp, err := h.ChainKit.GetBlockHeader(ctxt, req)
-	h.NoError(err, "GetBlockHeader")
-
-	return resp
-}
-
 // GetBlockHash makes an RPC call to chain kit client's GetBlockHash and
 // asserts.
 func (h *HarnessRPC) GetBlockHash(
diff --git a/lnwallet/chainfee/estimator_test.go b/lnwallet/chainfee/estimator_test.go
index 8227b5f2b..fc16c9b12 100644
--- a/lnwallet/chainfee/estimator_test.go
+++ b/lnwallet/chainfee/estimator_test.go
@@ -3,27 +3,12 @@ package chainfee
 import (
 	"bytes"
 	"encoding/json"
-	"io"
-	"reflect"
 	"testing"
 
 	"github.com/btcsuite/btcd/btcutil"
 	"github.com/stretchr/testify/require"
 )
 
-type mockSparseConfFeeSource struct {
-	url  string
-	fees map[uint32]uint32
-}
-
-func (e mockSparseConfFeeSource) GenQueryURL() string {
-	return e.url
-}
-
-func (e mockSparseConfFeeSource) ParseResponse(r io.Reader) (map[uint32]uint32, error) {
-	return e.fees, nil
-}
-
 // TestFeeRateTypes checks that converting fee rates between the
 // different types that represent fee rates and calculating fees
 // work as expected.
@@ -113,10 +98,6 @@ func TestSparseConfFeeSource(t *testing.T) {
 	// Test that GenQueryURL returns the URL as is.
 	url := "test"
 	feeSource := SparseConfFeeSource{URL: url}
-	queryURL := feeSource.GenQueryURL()
-	if queryURL != url {
-		t.Fatalf("expected query URL of %v, got %v", url, queryURL)
-	}
 
 	// Test parsing a properly formatted JSON API response.
 	// First, create the response as a bytes.Reader.
@@ -125,17 +106,17 @@ func TestSparseConfFeeSource(t *testing.T) {
 		2: 42,
 		3: 54321,
 	}
-	testJSON := map[string]map[uint32]uint32{"fee_by_block_target": testFees}
+	testJSON := map[string]map[uint32]uint32{
+		"fee_by_block_target": testFees,
+	}
 	jsonResp, err := json.Marshal(testJSON)
 	require.NoError(t, err, "unable to marshal JSON API response")
 	reader := bytes.NewReader(jsonResp)
 
 	// Finally, ensure the expected map is returned without error.
-	fees, err := feeSource.ParseResponse(reader)
+	fees, err := feeSource.parseResponse(reader)
 	require.NoError(t, err, "unable to parse API response")
-	if !reflect.DeepEqual(fees, testFees) {
-		t.Fatalf("expected %v, got %v", testFees, fees)
-	}
+	require.Equal(t, testFees, fees, "unexpected fee map returned")
 
 	// Test parsing an improperly formatted JSON API response.
 	badFees := map[string]uint32{"hi": 12345, "hello": 42, "satoshi": 54321}
@@ -145,10 +126,8 @@ func TestSparseConfFeeSource(t *testing.T) {
 	reader = bytes.NewReader(jsonResp)
 
 	// Finally, ensure the improperly formatted fees error.
-	_, err = feeSource.ParseResponse(reader)
-	if err == nil {
-		t.Fatalf("expected ParseResponse to fail")
-	}
+	_, err = feeSource.parseResponse(reader)
+	require.Error(t, err, "expected error when parsing bad JSON")
 }
 
 // TestWebAPIFeeEstimator checks that the WebAPIFeeEstimator returns fee rates
@@ -216,10 +195,9 @@ func TestWebAPIFeeEstimator(t *testing.T) {
 		maxTarget: minFeeRate,
 	}
 
-	feeSource := mockSparseConfFeeSource{
-		url:  "https://www.github.com",
-		fees: feeRateResp,
-	}
+	// Create a mock fee source and mock its returned map.
+	feeSource := &mockFeeSource{}
+	feeSource.On("GetFeeMap").Return(feeRateResp, nil)
 
 	estimator := NewWebAPIEstimator(feeSource, false)
 
@@ -250,12 +228,15 @@ func TestWebAPIFeeEstimator(t *testing.T) {
 
 			exp := SatPerKVByte(tc.expectedFeeRate).FeePerKWeight()
 			require.Equalf(t, exp, est, "target %v failed, fee "+
-				"map is %v", tc.target, feeSource.fees)
+				"map is %v", tc.target, feeRateResp)
 		})
 	}
 
 	// Stop the estimator when test ends.
 	require.NoError(t, estimator.Stop(), "unable to stop fee estimator")
+
+	// Assert the mocked fee source is called as expected.
+	feeSource.AssertExpectations(t)
 }
 
 // TestGetCachedFee checks that the fee caching logic works as expected.
diff --git a/routing/notifications_test.go b/routing/notifications_test.go
index 00bc29f6b..658df5423 100644
--- a/routing/notifications_test.go
+++ b/routing/notifications_test.go
@@ -228,20 +228,6 @@ func (m *mockChain) GetBlock(blockHash *chainhash.Hash) (*wire.MsgBlock, error)
 	return block, nil
 }
 
-func (m *mockChain) GetBlockHeader(
-	blockHash *chainhash.Hash) (*wire.BlockHeader, error) {
-
-	m.RLock()
-	defer m.RUnlock()
-
-	block, ok := m.blocks[*blockHash]
-	if !ok {
-		return nil, fmt.Errorf("block not found")
-	}
-
-	return &block.Header, nil
-}
-
 type mockChainView struct {
 	sync.RWMutex