Skip to content

Commit aa27ba9

Browse files
committed
Merge branch 'main' into lending
2 parents 045327b + 535d595 commit aa27ba9

22 files changed

+845
-582
lines changed

api/side/btcbridge/btcbridge.pulsar.go

Lines changed: 103 additions & 103 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

api/side/btcbridge/params.pulsar.go

Lines changed: 287 additions & 151 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

docs/static/openapi.yml

Lines changed: 1 addition & 1 deletion
Large diffs are not rendered by default.

local_node.sh

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ MAX_GAS=10000000000
2020
# btcbridge params
2121
BTC_VAULT=() # ("<address>" "<pk>" "<asset type>")
2222
RUNES_VAULT=()
23+
TRUSTED_BTC_RELAYER=""
2324
TRUSTED_NON_BTC_RELAYER=""
2425
TRUSTED_ORACLE=""
2526
PROTOCOL_FEE_COLLECTOR=""
@@ -96,7 +97,6 @@ if [[ $overwrite == "y" || $overwrite == "Y" ]]; then
9697
jq --arg denom "${DENOMS[0]}" '.app_state["crisis"]["constant_fee"]["denom"]=$denom' "$GENESIS" >"$TMP_GENESIS" && mv "$TMP_GENESIS" "$GENESIS"
9798
jq --arg denom "${DENOMS[0]}" '.app_state["gov"]["deposit_params"]["min_deposit"][0]["denom"]=$denom' "$GENESIS" >"$TMP_GENESIS" && mv "$TMP_GENESIS" "$GENESIS"
9899
jq --arg denom "${DENOMS[0]}" '.app_state["gov"]["params"]["min_deposit"][0]["denom"]=$denom' "$GENESIS" >"$TMP_GENESIS" && mv "$TMP_GENESIS" "$GENESIS"
99-
jq --arg gas "$BLOCK_GAS" '.app_state["feemarket"]["block_gas"]=$gas' "$GENESIS" >"$TMP_GENESIS" && mv "$TMP_GENESIS" "$GENESIS"
100100
# Set gas limit in genesis
101101
jq --arg max_gas "$MAX_GAS" '.consensus_params["block"]["max_gas"]=$max_gas' "$GENESIS" >"$TMP_GENESIS" && mv "$TMP_GENESIS" "$GENESIS"
102102

@@ -120,6 +120,11 @@ if [[ $overwrite == "y" || $overwrite == "Y" ]]; then
120120
jq --arg runes_vault_asset_type "${RUNES_VAULT[2]}" '.app_state["btcbridge"]["params"]["vaults"][1]["asset_type"]=$runes_vault_asset_type' "$GENESIS" >"$TMP_GENESIS" && mv "$TMP_GENESIS" "$GENESIS"
121121
fi
122122

123+
# set trusted btc relayer
124+
if [ -n "$TRUSTED_BTC_RELAYER" ]; then
125+
jq --arg relayer "$TRUSTED_BTC_RELAYER" '.app_state["btcbridge"]["params"]["trusted_btc_relayers"][0]=$relayer' "$GENESIS" >"$TMP_GENESIS" && mv "$TMP_GENESIS" "$GENESIS"
126+
fi
127+
123128
# set trusted non btc relayer
124129
if [ -n "$TRUSTED_NON_BTC_RELAYER" ]; then
125130
jq --arg relayer "$TRUSTED_NON_BTC_RELAYER" '.app_state["btcbridge"]["params"]["trusted_non_btc_relayers"][0]=$relayer' "$GENESIS" >"$TMP_GENESIS" && mv "$TMP_GENESIS" "$GENESIS"

local_node_dev.sh

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ MAX_GAS=10000000000
2020
# btcbridge params
2121
BTC_VAULT=() # ("<address>" "<pk>" "<asset type>")
2222
RUNES_VAULT=()
23+
TRUSTED_BTC_RELAYER=""
2324
TRUSTED_NON_BTC_RELAYER=""
2425
TRUSTED_ORACLE=""
2526
PROTOCOL_FEE_COLLECTOR=""
@@ -96,7 +97,6 @@ if [[ $overwrite == "y" || $overwrite == "Y" ]]; then
9697
jq --arg denom "${DENOMS[0]}" '.app_state["crisis"]["constant_fee"]["denom"]=$denom' "$GENESIS" >"$TMP_GENESIS" && mv "$TMP_GENESIS" "$GENESIS"
9798
jq --arg denom "${DENOMS[0]}" '.app_state["gov"]["deposit_params"]["min_deposit"][0]["denom"]=$denom' "$GENESIS" >"$TMP_GENESIS" && mv "$TMP_GENESIS" "$GENESIS"
9899
jq --arg denom "${DENOMS[0]}" '.app_state["gov"]["params"]["min_deposit"][0]["denom"]=$denom' "$GENESIS" >"$TMP_GENESIS" && mv "$TMP_GENESIS" "$GENESIS"
99-
jq --arg gas "$BLOCK_GAS" '.app_state["feemarket"]["block_gas"]=$gas' "$GENESIS" >"$TMP_GENESIS" && mv "$TMP_GENESIS" "$GENESIS"
100100
# Set gas limit in genesis
101101
jq --arg max_gas "$MAX_GAS" '.consensus_params["block"]["max_gas"]=$max_gas' "$GENESIS" >"$TMP_GENESIS" && mv "$TMP_GENESIS" "$GENESIS"
102102

@@ -120,6 +120,11 @@ if [[ $overwrite == "y" || $overwrite == "Y" ]]; then
120120
jq --arg runes_vault_asset_type "${RUNES_VAULT[2]}" '.app_state["btcbridge"]["params"]["vaults"][1]["asset_type"]=$runes_vault_asset_type' "$GENESIS" >"$TMP_GENESIS" && mv "$TMP_GENESIS" "$GENESIS"
121121
fi
122122

123+
# set trusted btc relayer
124+
if [ -n "$TRUSTED_BTC_RELAYER" ]; then
125+
jq --arg relayer "$TRUSTED_BTC_RELAYER" '.app_state["btcbridge"]["params"]["trusted_btc_relayers"][0]=$relayer' "$GENESIS" >"$TMP_GENESIS" && mv "$TMP_GENESIS" "$GENESIS"
126+
fi
127+
123128
# set trusted non btc relayer
124129
if [ -n "$TRUSTED_NON_BTC_RELAYER" ]; then
125130
jq --arg relayer "$TRUSTED_NON_BTC_RELAYER" '.app_state["btcbridge"]["params"]["trusted_non_btc_relayers"][0]=$relayer' "$GENESIS" >"$TMP_GENESIS" && mv "$TMP_GENESIS" "$GENESIS"

proto/side/btcbridge/btcbridge.proto

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -123,8 +123,8 @@ message DKGParticipant {
123123
string moniker = 1;
124124
// the operator address of the corresponding validator
125125
string operator_address = 2;
126-
// the consensus address of the corresponding validator
127-
string consensus_address = 3;
126+
// the consensus public key of the corresponding validator
127+
string consensus_pubkey = 3;
128128
}
129129

130130
enum DKGRequestStatus {

proto/side/btcbridge/params.proto

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -19,22 +19,24 @@ message Params {
1919
bool deposit_enabled = 4;
2020
// Indicates if withdrawal is enabled
2121
bool withdraw_enabled = 5;
22+
// Trusted relayers to submit bitcoin block headers
23+
repeated string trusted_btc_relayers = 6;
2224
// Trusted relayers for non-btc asset deposit
23-
repeated string trusted_non_btc_relayers = 6;
25+
repeated string trusted_non_btc_relayers = 7;
2426
// Trusted oracles for providing offchain data, e.g. bitcoin fee rate
25-
repeated string trusted_oracles = 7;
27+
repeated string trusted_oracles = 8;
2628
// Period of validity for the fee rate
27-
int64 fee_rate_validity_period = 8;
29+
int64 fee_rate_validity_period = 9;
2830
// Asset vaults
29-
repeated Vault vaults = 9;
31+
repeated Vault vaults = 10;
3032
// Withdrawal params
31-
WithdrawParams withdraw_params = 10 [(gogoproto.nullable) = false];
33+
WithdrawParams withdraw_params = 11 [(gogoproto.nullable) = false];
3234
// Protocol limitations
33-
ProtocolLimits protocol_limits = 11 [(gogoproto.nullable) = false];
35+
ProtocolLimits protocol_limits = 12 [(gogoproto.nullable) = false];
3436
// Protocol fees
35-
ProtocolFees protocol_fees = 12 [(gogoproto.nullable) = false];
37+
ProtocolFees protocol_fees = 13 [(gogoproto.nullable) = false];
3638
// TSS params
37-
TSSParams tss_params = 13 [(gogoproto.nullable) = false];
39+
TSSParams tss_params = 14 [(gogoproto.nullable) = false];
3840
}
3941

4042
// AssetType defines the type of asset

x/btcbridge/keeper/keeper.go

Lines changed: 57 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"bytes"
55
"encoding/base64"
66
"fmt"
7+
"math/big"
78

89
"github.com/btcsuite/btcd/blockchain"
910
"github.com/btcsuite/btcd/btcutil"
@@ -95,73 +96,72 @@ func (k Keeper) SetBlockHeader(ctx sdk.Context, header *types.BlockHeader) {
9596
store.Set(types.BtcBlockHeaderHeightKey(header.Height), []byte(header.Hash))
9697
}
9798

98-
func (k Keeper) SetBlockHeaders(ctx sdk.Context, blockHeaders []*types.BlockHeader) error {
99+
func (k Keeper) SetBlockHeaders(ctx sdk.Context, headers []*types.BlockHeader) {
100+
for _, h := range headers {
101+
k.SetBlockHeader(ctx, h)
102+
}
103+
}
104+
105+
func (k Keeper) InsertBlockHeaders(ctx sdk.Context, blockHeaders []*types.BlockHeader) error {
99106
store := ctx.KVStore(k.storeKey)
100107

101-
// first check if some block header already exists
102-
for _, header := range blockHeaders {
103-
if store.Has(types.BtcBlockHeaderHashKey(header.Hash)) {
104-
// return no error
105-
return nil
106-
}
108+
startBlockHeader := blockHeaders[0]
109+
newBestBlockHeader := blockHeaders[len(blockHeaders)-1]
110+
111+
// check if the starting block header already exists
112+
if store.Has(types.BtcBlockHeaderHashKey(startBlockHeader.Hash)) {
113+
// return no error
114+
return nil
107115
}
108116

109117
params := k.GetParams(ctx)
110118

111119
// get the best block header
112120
best := k.GetBestBlockHeader(ctx)
113121

114-
for _, header := range blockHeaders {
115-
// validate the block header
116-
if err := header.Validate(); err != nil {
117-
return err
122+
if startBlockHeader.PreviousBlockHash == best.Hash {
123+
if startBlockHeader.Height != best.Height+1 {
124+
return errorsmod.Wrap(types.ErrInvalidBlockHeaders, "invalid block height")
125+
}
126+
} else {
127+
// reorg detected
128+
// check if the reorg depth exceeds the safe confirmations
129+
if best.Height-startBlockHeader.Height+1 > uint64(params.Confirmations) {
130+
return types.ErrInvalidReorgDepth
118131
}
119132

120133
// check if the previous block exists
121-
if !store.Has(types.BtcBlockHeaderHashKey(header.PreviousBlockHash)) {
122-
return errorsmod.Wrap(types.ErrInvalidBlockHeader, "previous block does not exist")
134+
if !store.Has(types.BtcBlockHeaderHashKey(startBlockHeader.PreviousBlockHash)) {
135+
return errorsmod.Wrap(types.ErrInvalidBlockHeaders, "previous block does not exist")
123136
}
124137

125138
// check the block height
126-
prevBlock := k.GetBlockHeader(ctx, header.PreviousBlockHash)
127-
if header.Height != prevBlock.Height+1 {
128-
return errorsmod.Wrap(types.ErrInvalidBlockHeader, "incorrect block height")
139+
prevBlock := k.GetBlockHeader(ctx, startBlockHeader.PreviousBlockHash)
140+
if startBlockHeader.Height != prevBlock.Height+1 {
141+
return errorsmod.Wrap(types.ErrInvalidBlockHeaders, "invalid block height")
129142
}
130143

131-
// check whether it's next block header or not
132-
if best.Hash != header.PreviousBlockHash {
133-
// check if the reorg depth exceeds the safe confirmations
134-
if best.Height-header.Height+1 > uint64(params.Confirmations) {
135-
return types.ErrInvalidReorgDepth
136-
}
137-
138-
// check if the new block header has more work than the old one
139-
oldNode := k.GetBlockHeaderByHeight(ctx, header.Height)
140-
worksOld := blockchain.CalcWork(types.BitsToTargetUint32(oldNode.Bits))
141-
worksNew := blockchain.CalcWork(types.BitsToTargetUint32(header.Bits))
142-
if sdk.GetConfig().GetBtcChainCfg().Net == wire.MainNet && worksNew.Cmp(worksOld) <= 0 || worksNew.Cmp(worksOld) < 0 {
143-
return types.ErrForkedBlockHeader
144-
}
145-
146-
// remove the block headers after the forked block header
147-
// and consider the forked block header as the best block header
148-
for i := header.Height; i <= best.Height; i++ {
149-
ctx.Logger().Info("Removing block header: ", i)
150-
thash := k.GetBlockHashByHeight(ctx, i)
151-
store.Delete(types.BtcBlockHeaderHashKey(thash))
152-
store.Delete(types.BtcBlockHeaderHeightKey(i))
153-
}
144+
// check if the new block headers has more work than the work accumulated from the forked block to the current tip
145+
totalWorkOldToTip := k.CalcTotalWork(ctx, startBlockHeader.Height, best.Height)
146+
totalWorkNew := types.BlockHeaders(blockHeaders).GetTotalWork()
147+
if sdk.GetConfig().GetBtcChainCfg().Net == wire.MainNet && totalWorkNew.Cmp(totalWorkOldToTip) <= 0 || totalWorkNew.Cmp(totalWorkOldToTip) < 0 {
148+
return errorsmod.Wrap(types.ErrInvalidBlockHeaders, "invalid forking block headers")
154149
}
155150

156-
// set the block header
157-
k.SetBlockHeader(ctx, header)
158-
159-
// update the best block header
160-
best = header
151+
// remove the block headers starting from the forked block height
152+
for i := startBlockHeader.Height; i <= best.Height; i++ {
153+
ctx.Logger().Info("Removing block header: ", i)
154+
thash := k.GetBlockHashByHeight(ctx, i)
155+
store.Delete(types.BtcBlockHeaderHashKey(thash))
156+
store.Delete(types.BtcBlockHeaderHeightKey(i))
157+
}
161158
}
162159

160+
// set block headers
161+
k.SetBlockHeaders(ctx, blockHeaders)
162+
163163
// set the best block header
164-
k.SetBestBlockHeader(ctx, best)
164+
k.SetBestBlockHeader(ctx, newBestBlockHeader)
165165

166166
return nil
167167
}
@@ -210,6 +210,18 @@ func (k Keeper) IterateBlockHeaders(ctx sdk.Context, process func(header types.B
210210
}
211211
}
212212

213+
// CalcTotalWork calculates the total work of the given range of block headers
214+
func (k Keeper) CalcTotalWork(ctx sdk.Context, startHeight uint64, endHeight uint64) *big.Int {
215+
totalWork := new(big.Int)
216+
217+
for i := startHeight; i <= endHeight; i++ {
218+
work := k.GetBlockHeaderByHeight(ctx, i).GetWork()
219+
totalWork = new(big.Int).Add(totalWork, work)
220+
}
221+
222+
return totalWork
223+
}
224+
213225
// ValidateTransaction validates the given transaction
214226
func (k Keeper) ValidateTransaction(ctx sdk.Context, txBytes string, prevTxBytes string, blockHash string, proof []string) (*btcutil.Tx, *btcutil.Tx, error) {
215227
params := k.GetParams(ctx)

x/btcbridge/keeper/keeper_test.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -188,13 +188,13 @@ func (suite *KeeperTestSuite) TestWithdrawRunes() {
188188
denom := fmt.Sprintf("%s/%s", types.RunesProtocolName, runeId)
189189
coin := sdk.NewInt64Coin(denom, int64(amount))
190190

191-
_, err := suite.app.BtcBridgeKeeper.NewSigningRequest(suite.ctx, suite.sender, coin, int64(feeRate))
191+
_, err := suite.app.BtcBridgeKeeper.NewRunesSigningRequest(suite.ctx, suite.sender, coin, int64(feeRate), suite.runesVault, suite.btcVault)
192192
suite.ErrorIs(err, types.ErrInsufficientUTXOs, "should fail due to insufficient runes utxos")
193193

194194
amount = 100000000
195195
coin = sdk.NewInt64Coin(denom, int64(amount))
196196

197-
_, err = suite.app.BtcBridgeKeeper.NewSigningRequest(suite.ctx, suite.sender, coin, int64(feeRate))
197+
_, err = suite.app.BtcBridgeKeeper.NewRunesSigningRequest(suite.ctx, suite.sender, coin, int64(feeRate), suite.runesVault, suite.btcVault)
198198
suite.ErrorIs(err, types.ErrInsufficientUTXOs, "should fail due to insufficient payment utxos")
199199

200200
paymentUTXOs := []*types.UTXO{
@@ -209,7 +209,7 @@ func (suite *KeeperTestSuite) TestWithdrawRunes() {
209209
}
210210
suite.setupUTXOs(paymentUTXOs)
211211

212-
req, err := suite.app.BtcBridgeKeeper.NewSigningRequest(suite.ctx, suite.sender, coin, int64(feeRate))
212+
req, err := suite.app.BtcBridgeKeeper.NewRunesSigningRequest(suite.ctx, suite.sender, coin, int64(feeRate), suite.runesVault, suite.btcVault)
213213
suite.NoError(err)
214214

215215
suite.False(suite.app.BtcBridgeKeeper.HasUTXO(suite.ctx, runesUTXOs[0].Txid, runesUTXOs[0].Vout), "runes utxo should be spent")

x/btcbridge/keeper/msg_server.go

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,12 @@ func (m msgServer) SubmitBlockHeaders(goCtx context.Context, msg *types.MsgSubmi
2626
return nil, err
2727
}
2828

29-
// Set block headers
30-
err := m.SetBlockHeaders(ctx, msg.BlockHeaders)
29+
if !m.IsTrustedBtcRelayer(ctx, msg.Sender) {
30+
return nil, types.ErrUntrustedBtcRelayer
31+
}
32+
33+
// insert block headers
34+
err := m.InsertBlockHeaders(ctx, msg.BlockHeaders)
3135
if err != nil {
3236
return nil, err
3337
}
@@ -64,7 +68,7 @@ func (m msgServer) UpdateTrustedOracles(goCtx context.Context, msg *types.MsgUpd
6468
}
6569

6670
if !m.IsTrustedOracle(ctx, msg.Sender) {
67-
return nil, types.ErruntrustedOracle
71+
return nil, types.ErrUntrustedOracle
6872
}
6973

7074
// update oracles
@@ -138,7 +142,7 @@ func (m msgServer) SubmitFeeRate(goCtx context.Context, msg *types.MsgSubmitFeeR
138142
}
139143

140144
if !m.IsTrustedOracle(ctx, msg.Sender) {
141-
return nil, types.ErruntrustedOracle
145+
return nil, types.ErrUntrustedOracle
142146
}
143147

144148
m.SetFeeRate(ctx, msg.FeeRate)

0 commit comments

Comments
 (0)