add: filecoin message validation, secp signature

This commit is contained in:
bahadylbekov 2020-12-02 17:03:39 +03:00
parent 221cf45dad
commit a42776be67
22 changed files with 2929 additions and 62 deletions

View File

@ -28,7 +28,7 @@ func ComputeVRF(sign SignFunc, worker peer.ID, sigInput []byte) ([]byte, error)
} }
func VerifyVRF(worker peer.ID, vrfBase, vrfproof []byte) error { func VerifyVRF(worker peer.ID, vrfBase, vrfproof []byte) error {
err := sigs.Verify(&types.Signature{Type: types.SigTypeEd25519, Data: vrfproof}, worker, vrfBase) err := sigs.Verify(&types.Signature{Type: types.SigTypeEd25519, Data: vrfproof}, []byte(worker), vrfBase)
if err != nil { if err != nil {
return xerrors.Errorf("vrf was invalid: %w", err) return xerrors.Errorf("vrf was invalid: %w", err)
} }

View File

@ -132,7 +132,6 @@ func (m *Miner) MineTask(ctx context.Context, event *oracleEmitter.OracleEmitter
if err != nil { if err != nil {
return nil, xerrors.Errorf("couldn't do rpc request: %w", err) return nil, xerrors.Errorf("couldn't do rpc request: %w", err)
} }
bres := []byte(res)
return &types.DioneTask{ return &types.DioneTask{
OriginChain: event.OriginChain, OriginChain: event.OriginChain,
@ -143,7 +142,7 @@ func (m *Miner) MineTask(ctx context.Context, event *oracleEmitter.OracleEmitter
Ticket: ticket, Ticket: ticket,
ElectionProof: winner, ElectionProof: winner,
BeaconEntries: beaconValues, BeaconEntries: beaconValues,
Payload: bres, Payload: res,
DrandRound: types.DrandRound(randomBase.Round), DrandRound: types.DrandRound(randomBase.Round),
}, nil }, nil
} }

View File

@ -1,6 +1,7 @@
package consensus package consensus
import ( import (
"bytes"
"fmt" "fmt"
oracleEmitter "github.com/Secured-Finance/dione/contracts/oracleemitter" oracleEmitter "github.com/Secured-Finance/dione/contracts/oracleemitter"
@ -9,7 +10,9 @@ import (
"github.com/filecoin-project/go-state-types/crypto" "github.com/filecoin-project/go-state-types/crypto"
ftypes "github.com/Secured-Finance/dione/rpc/filecoin/types"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/filecoin-project/go-state-types/crypto"
types2 "github.com/Secured-Finance/dione/consensus/types" types2 "github.com/Secured-Finance/dione/consensus/types"
"github.com/Secured-Finance/dione/sigs" "github.com/Secured-Finance/dione/sigs"
@ -92,6 +95,18 @@ func (ppp *PrePreparePool) IsValidPrePrepare(prePrepare *types2.Message) bool {
logrus.Errorf("the incoming task and cached request event don't match!") logrus.Errorf("the incoming task and cached request event don't match!")
return false return false
// === verify filecoin message signature ===
if consensusMsg.Task.RequestType == "GetTransaction" && consensusMsg.Task.OriginChain == 1 {
var msg ftypes.SignedMessage
if err := msg.UnmarshalCBOR(bytes.NewReader(consensusMsg.Task.Payload)); err != nil {
if err := msg.Message.UnmarshalCBOR(bytes.NewReader(consensusMsg.Task.Payload)); err != nil {
return false
}
}
if err = sigs.Verify(msg.Signature, msg.Message.From.Bytes(), msg.Message.Cid().Bytes()); err != nil {
logrus.Errorf("Couldn't verify transaction %v", err)
}
} }
///////////////////////////////// /////////////////////////////////

View File

@ -16,7 +16,7 @@ func verifyTaskSignature(msg types.ConsensusMessage) error {
} }
err = sigs.Verify( err = sigs.Verify(
&types2.Signature{Type: types2.SigTypeEd25519, Data: msg.Signature}, &types2.Signature{Type: types2.SigTypeEd25519, Data: msg.Signature},
msg.Task.Miner, []byte(msg.Task.Miner.String()),
[]byte(fmt.Sprintf("%v", cHash)), []byte(fmt.Sprintf("%v", cHash)),
) )
if err != nil { if err != nil {

View File

@ -0,0 +1,2 @@
node_modules
contracts/Migrations.sol

View File

@ -0,0 +1,20 @@
{
"extends": "solium:recommended",
"plugins": [
"security"
],
"rules": {
"quotes": [
"error",
"double"
],
"indentation": [
"error",
4
],
"linebreak-style": [
"error",
"unix"
]
}
}

View File

@ -4,14 +4,19 @@ pragma solidity ^0.6.12;
import "@openzeppelin/contracts/math/SafeMath.sol"; import "@openzeppelin/contracts/math/SafeMath.sol";
import "@openzeppelin/contracts/access/Ownable.sol"; import "@openzeppelin/contracts/access/Ownable.sol";
import "./interfaces/DioneStakingInterface.sol"; import "./interfaces/IDioneStaking.sol";
contract DioneOracle is Ownable { contract DioneOracle is Ownable {
using SafeMath for uint256; using SafeMath for uint256;
// Global counter of oracle requests, works as an index in mapping structures
uint256 private requestCounter; uint256 private requestCounter;
// Maximum time for computing oracle request
uint256 constant public MAXIMUM_DELAY = 5 minutes; uint256 constant public MAXIMUM_DELAY = 5 minutes;
DioneStakingInterface public dioneStaking; // Dione staking contract
IDioneStaking public dioneStaking;
// Minimum amount of DIONE tokens required to vote against miner result
uint256 public minimumDisputeFee = 100**18;
struct OracleRequest { struct OracleRequest {
uint8 originChain; // origin blockchain for request uint8 originChain; // origin blockchain for request
@ -51,7 +56,7 @@ contract DioneOracle is Ownable {
); );
modifier onlyPendingRequest(uint256 _reqID) { modifier onlyPendingRequest(uint256 _reqID) {
require(pendingRequests[_reqID] != 0, "Invalid requestId"); require(pendingRequests[_reqID] != 0, "This request is not pending");
_; _;
} }
@ -60,7 +65,7 @@ contract DioneOracle is Ownable {
_; _;
} }
constructor(DioneStakingInterface _dioneStaking) public { constructor(IDioneStaking _dioneStaking) public {
dioneStaking = _dioneStaking; dioneStaking = _dioneStaking;
} }
@ -83,7 +88,7 @@ contract DioneOracle is Ownable {
emit CancelOracleRequest(_reqID); emit CancelOracleRequest(_reqID);
} }
function submitOracleRequest(string memory _requestParams, address _callbackAddress, bytes4 _callbackMethodID, uint256 _reqID, uint256 _requestDeadline, bytes memory _data) public onlyActiveNode returns (bool) { function submitOracleRequest(string memory _requestParams, address _callbackAddress, bytes4 _callbackMethodID, uint256 _reqID, uint256 _requestDeadline, bytes memory _data) public onlyPendingRequest(_reqID) onlyActiveNode returns (bool) {
bytes32 requestHash = keccak256(abi.encodePacked(_requestParams, _callbackAddress, _callbackMethodID, _reqID, _requestDeadline)); bytes32 requestHash = keccak256(abi.encodePacked(_requestParams, _callbackAddress, _callbackMethodID, _reqID, _requestDeadline));
require(pendingRequests[_reqID] == requestHash, "Params do not match request ID"); require(pendingRequests[_reqID] == requestHash, "Params do not match request ID");
delete pendingRequests[_reqID]; delete pendingRequests[_reqID];

View File

@ -1,6 +1,8 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.6.0; pragma solidity ^0.6.0;
interface DioneStakingInterface { interface IDioneStaking {
function mine(address _minerAddr) external; function mine(address _minerAddr) external;
function mineAndStake(address _minerAddr) external; function mineAndStake(address _minerAddr) external;
function stake(uint256 _amount) external; function stake(uint256 _amount) external;

View File

@ -0,0 +1,125 @@
// SPDX-License-Identifier: MIT
pragma solidity >=0.6.0 <0.8.0;
/**
* @dev Interface of the ERC20 standard as defined in the EIP.
*/
interface IDioneToken {
/**
* @dev Returns the amount of tokens in existence.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns the amount of tokens owned by `account`.
*/
function balanceOf(address account) external view returns (uint256);
/**
* @dev Moves `amount` tokens from the caller's account to `recipient`.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transfer(address recipient, uint256 amount) external returns (bool);
/**
* @dev Returns the remaining number of tokens that `spender` will be
* allowed to spend on behalf of `owner` through {transferFrom}. This is
* zero by default.
*
* This value changes when {approve} or {transferFrom} are called.
*/
function allowance(address owner, address spender) external view returns (uint256);
/**
* @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* IMPORTANT: Beware that changing an allowance with this method brings the risk
* that someone may use both the old and the new allowance by unfortunate
* transaction ordering. One possible solution to mitigate this race
* condition is to first reduce the spender's allowance to 0 and set the
* desired value afterwards:
* https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
*
* Emits an {Approval} event.
*/
function approve(address spender, uint256 amount) external returns (bool);
/**
* @dev Moves `amount` tokens from `sender` to `recipient` using the
* allowance mechanism. `amount` is then deducted from the caller's
* allowance.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);
/**
* @dev Emitted when `value` tokens are moved from one account (`from`) to
* another (`to`).
*
* Note that `value` may be zero.
*/
event Transfer(address indexed from, address indexed to, uint256 value);
/**
* @dev Emitted when the allowance of a `spender` for an `owner` is set by
* a call to {approve}. `value` is the new allowance.
*/
event Approval(address indexed owner, address indexed spender, uint256 value);
/// @notice Creates `_amount` token to `_to`. Must only be called by the owner (MasterChef).
function mint(address _to, uint256 _amount) external;
/// @notice An event thats emitted when an account changes its delegate
event DelegateChanged(address indexed delegator, address indexed fromDelegate, address indexed toDelegate);
/// @notice An event thats emitted when a delegate account's vote balance changes
event DelegateVotesChanged(address indexed delegate, uint previousBalance, uint newBalance);
/**
* @notice Delegate votes from `msg.sender` to `delegatee`
* @param delegator The address to get delegatee for
*/
function delegates(address delegator) external view returns (address);
/**
* @notice Delegate votes from `msg.sender` to `delegatee`
* @param delegatee The address to delegate votes to
*/
function delegate(address delegatee) external;
/**
* @notice Delegates votes from signatory to `delegatee`
* @param delegatee The address to delegate votes to
* @param nonce The contract state required to match the signature
* @param expiry The time at which to expire the signature
* @param v The recovery byte of the signature
* @param r Half of the ECDSA signature pair
* @param s Half of the ECDSA signature pair
*/
function delegateBySig(address delegatee, uint nonce, uint expiry, uint8 v, bytes32 r, bytes32 s) external;
/**
* @notice Gets the current votes balance for `account`
* @param account The address to get votes balance
* @return The number of current votes for `account`
*/
function getCurrentVotes(address account) external view returns (uint256);
/**
* @notice Determine the prior number of votes for an account as of a block number
* @dev Block number must be a finalized block or else this function will revert to prevent misinformation.
* @param account The address of the account to check
* @param blockNumber The block number to get the vote balance at
* @return The number of votes the account had as of the given block
*/
function getPriorVotes(address account, uint blockNumber) external view returns (uint256);
}

File diff suppressed because it is too large Load Diff

View File

@ -8,13 +8,15 @@
}, },
"scripts": { "scripts": {
"test": "echo \"Error: no test specified\" && exit 1", "test": "echo \"Error: no test specified\" && exit 1",
"compile": "truffle compile" "compile": "truffle compile",
"fix-lint": "solium -d contracts/ --fix"
}, },
"author": "", "author": "",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@truffle/hdwallet-provider": "^1.0.40", "@truffle/hdwallet-provider": "^1.0.40",
"dotenv": "^8.2.0", "dotenv": "^8.2.0",
"ethlint": "^1.2.5",
"truffle": "^5.1.37", "truffle": "^5.1.37",
"truffle-export-abi": "^1.0.1", "truffle-export-abi": "^1.0.1",
"truffle-flattener": "^1.5.0" "truffle-flattener": "^1.5.0"

16
go.mod
View File

@ -16,8 +16,10 @@ require (
github.com/drand/kyber v1.1.5 github.com/drand/kyber v1.1.5
github.com/elastic/gosigar v0.10.5 // indirect github.com/elastic/gosigar v0.10.5 // indirect
github.com/ethereum/go-ethereum v1.9.5 github.com/ethereum/go-ethereum v1.9.5
github.com/filecoin-project/go-address v0.0.4 github.com/filecoin-project/go-address v0.0.5-0.20201103152444-f2023ef3f5bb
github.com/filecoin-project/go-state-types v0.0.0-20201021025442-0ac4de847f4f github.com/filecoin-project/go-crypto v0.0.0-20191218222705-effae4ea9f03
github.com/filecoin-project/go-state-types v0.0.0-20201102161440-c8033295a1fc
github.com/filecoin-project/lotus v1.2.1
github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5 // indirect github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5 // indirect
github.com/fxamacker/cbor/v2 v2.2.0 github.com/fxamacker/cbor/v2 v2.2.0
github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08 // indirect github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08 // indirect
@ -30,18 +32,16 @@ require (
github.com/gopherjs/gopherjs v0.0.0-20190812055157-5d271430af9f // indirect github.com/gopherjs/gopherjs v0.0.0-20190812055157-5d271430af9f // indirect
github.com/ipfs/go-datastore v0.4.5 // indirect github.com/ipfs/go-datastore v0.4.5 // indirect
github.com/ipfs/go-ds-badger2 v0.1.1-0.20200708190120-187fc06f714e // indirect github.com/ipfs/go-ds-badger2 v0.1.1-0.20200708190120-187fc06f714e // indirect
github.com/ipfs/go-ipld-cbor v0.0.5-0.20200428170625-a0bd04d3cbdf // indirect
github.com/ipfs/go-ipld-format v0.2.0 // indirect github.com/ipfs/go-ipld-format v0.2.0 // indirect
github.com/ipfs/go-log v1.0.4 github.com/ipfs/go-log v1.0.4
github.com/ipfs/go-log/v2 v2.1.2-0.20200626104915-0016c0b4b3e4 // indirect github.com/ipfs/go-log/v2 v2.1.2-0.20200626104915-0016c0b4b3e4 // indirect
github.com/jmoiron/sqlx v1.2.0 github.com/jmoiron/sqlx v1.2.0
github.com/karalabe/usb v0.0.0-20191104083709-911d15fe12a9 // indirect github.com/karalabe/usb v0.0.0-20191104083709-911d15fe12a9 // indirect
github.com/lib/pq v1.7.0 // indirect github.com/lib/pq v1.7.0 // indirect
github.com/libp2p/go-libp2p v0.11.0 github.com/libp2p/go-libp2p v0.12.0
github.com/libp2p/go-libp2p-core v0.6.1 github.com/libp2p/go-libp2p-core v0.7.0
github.com/libp2p/go-libp2p-noise v0.1.2 // indirect github.com/libp2p/go-libp2p-noise v0.1.2 // indirect
github.com/libp2p/go-libp2p-pubsub v0.3.6 github.com/libp2p/go-libp2p-pubsub v0.4.0
github.com/libp2p/go-libp2p-testing v0.1.2-0.20200422005655-8775583591d8 // indirect
github.com/mattn/go-colorable v0.1.6 // indirect github.com/mattn/go-colorable v0.1.6 // indirect
github.com/mattn/go-sqlite3 v1.9.0 github.com/mattn/go-sqlite3 v1.9.0
github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1 github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1
@ -69,7 +69,7 @@ require (
github.com/wsddn/go-ecdh v0.0.0-20161211032359-48726bab9208 // indirect github.com/wsddn/go-ecdh v0.0.0-20161211032359-48726bab9208 // indirect
github.com/xorcare/golden v0.6.1-0.20191112154924-b87f686d7542 github.com/xorcare/golden v0.6.1-0.20191112154924-b87f686d7542
go.uber.org/fx v1.13.1 // indirect go.uber.org/fx v1.13.1 // indirect
go.uber.org/zap v1.15.0 go.uber.org/zap v1.16.0
golang.org/x/lint v0.0.0-20200302205851-738671d3881b // indirect golang.org/x/lint v0.0.0-20200302205851-738671d3881b // indirect
golang.org/x/tools v0.0.0-20200827010519-17fd2f27a9e3 // indirect golang.org/x/tools v0.0.0-20200827010519-17fd2f27a9e3 // indirect
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1

604
go.sum

File diff suppressed because it is too large Load Diff

View File

@ -131,7 +131,7 @@ func (n *Node) Run(ctx context.Context) error {
} }
} }
return nil // return nil
} }
func (n *Node) runLibp2pAsync(ctx context.Context) error { func (n *Node) runLibp2pAsync(ctx context.Context) error {
@ -271,12 +271,12 @@ func provideEthereumClient(config *config.Config) (*ethclient.EthereumClient, er
func (n *Node) setupRPCClients() error { func (n *Node) setupRPCClients() error {
fc := filecoin.NewLotusClient() fc := filecoin.NewLotusClient()
rpc.RegisterRPC(rtypes.RPCTypeFilecoin, map[string]func(string) (string, error){ rpc.RegisterRPC(rtypes.RPCTypeFilecoin, map[string]func(string) ([]byte, error){
"getTransaction": fc.GetTransaction, "getTransaction": fc.GetTransaction,
}) })
sl := solana2.NewSolanaClient() sl := solana2.NewSolanaClient()
rpc.RegisterRPC(rtypes.RPCTypeSolana, map[string]func(string) (string, error){ rpc.RegisterRPC(rtypes.RPCTypeSolana, map[string]func(string) ([]byte, error){
"getTransaction": sl.GetTransaction, "getTransaction": sl.GetTransaction,
}) })

View File

@ -1,11 +1,13 @@
package filecoin package filecoin
import ( import (
"bytes"
"encoding/json" "encoding/json"
"fmt" "fmt"
ftypes "github.com/Secured-Finance/dione/rpc/filecoin/types" ftypes "github.com/Secured-Finance/dione/rpc/filecoin/types"
"github.com/Secured-Finance/dione/rpc/types" "github.com/Secured-Finance/dione/rpc/types"
"github.com/filecoin-project/go-address"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
"github.com/valyala/fasthttp" "github.com/valyala/fasthttp"
@ -13,6 +15,11 @@ import (
var filecoinURL = "https://api.node.glif.io/" var filecoinURL = "https://api.node.glif.io/"
const (
blsType = 0x1
secp256k1Type = 0x2
)
// client implements the `Client` interface. // client implements the `Client` interface.
type LotusClient struct { type LotusClient struct {
host string host string
@ -38,11 +45,11 @@ func (c *LotusClient) GetTipSetByHeight(chainEpoch int64) ([]byte, error) {
return c.HandleRequest("Filecoin.ChainGetTipSetByHeight", i) return c.HandleRequest("Filecoin.ChainGetTipSetByHeight", i)
} }
func (c *LotusClient) GetTransaction(cid string) (string, error) { // func (c *LotusClient) GetTransaction(cid string) (string, error) {
i := ftypes.NewCidParam(cid) // i := ftypes.NewCidParam(cid)
resp, err := c.HandleRequest("Filecoin.ChainGetMessage", i) // resp, err := c.HandleRequest("Filecoin.ChainGetMessage", i)
return string(resp), err // return string(resp), err
} // }
func (c *LotusClient) GetNodeVersion() ([]byte, error) { func (c *LotusClient) GetNodeVersion() ([]byte, error) {
return c.HandleRequest("Filecoin.Version", nil) return c.HandleRequest("Filecoin.Version", nil)
@ -57,6 +64,42 @@ func (c *LotusClient) VerifyCid(cid string) ([]byte, error) {
return c.HandleRequest("Filecoin.ChainHasObj", i) return c.HandleRequest("Filecoin.ChainHasObj", i)
} }
// Gets signed transaction from Filecoin and returns SignedTransaction struct in byte slice
func (c *LotusClient) GetTransaction(cid string) ([]byte, error) {
i := ftypes.NewCidParam(cid)
bodyBytes, err := c.HandleRequest("Filecoin.ChainReadObj", i)
if err != nil {
return nil, fmt.Errorf("Failed to get object information %v", err)
}
var response types.RPCResponseBody
err = json.Unmarshal(bodyBytes, &response)
if err != nil {
return nil, fmt.Errorf("Failed to unmarshal response body %v", err)
}
var msg ftypes.SignedMessage
if err := msg.UnmarshalCBOR(bytes.NewReader(response.Result)); err != nil {
if err := msg.Message.UnmarshalCBOR(bytes.NewReader(response.Result)); err != nil {
return nil, err
}
}
switch msg.Message.From.Protocol() | msg.Message.To.Protocol() {
case address.BLS:
msg.Type = blsType
case address.SECP256K1:
msg.Type = secp256k1Type
default:
return nil, fmt.Errorf("Address has unsupported protocol %v", err)
}
b := new(bytes.Buffer)
if err := msg.MarshalCBOR(b); err != nil {
return nil, err
}
return b.Bytes(), nil
}
// HandleRequest implements the `Client` interface. // HandleRequest implements the `Client` interface.
func (c *LotusClient) HandleRequest(method string, params []interface{}) ([]byte, error) { func (c *LotusClient) HandleRequest(method string, params []interface{}) ([]byte, error) {
req := fasthttp.AcquireRequest() req := fasthttp.AcquireRequest()

View File

@ -1,27 +1,98 @@
package types package types
import ( import (
"github.com/filecoin-project/go-address" "fmt"
"github.com/filecoin-project/go-state-types/abi" "io"
"github.com/filecoin-project/go-state-types/crypto" "math"
"github.com/Secured-Finance/dione/types"
ltypes "github.com/filecoin-project/lotus/chain/types"
cbg "github.com/whyrusleeping/cbor-gen"
) )
type FilecoinMsg struct { type SignedMessage struct {
Version uint64 Message ltypes.Message
Signature *types.Signature
To address.Address Type MessageType
From address.Address
Nonce uint64
Value abi.TokenAmount
GasLimit int64
GasFeeCap abi.TokenAmount
GasPremium abi.TokenAmount
Method abi.MethodNum
Params []byte
} }
type FilMsgSignature *crypto.Signature type MessageType byte
const (
MessageTypeUnknown = MessageType(math.MaxUint8)
MessageTypeBLS = MessageType(iota)
MessageTypeSecp256k1 = MessageType(0x2)
)
func (t MessageType) Name() (string, error) {
switch t {
case MessageTypeUnknown:
return "unknown", nil
case MessageTypeBLS:
return "BLS", nil
case MessageTypeSecp256k1:
return "Secp256k1", nil
default:
return "", fmt.Errorf("invalid message signature type: %d", t)
}
}
// CBOR operations from lotus
func (t *SignedMessage) UnmarshalCBOR(r io.Reader) error {
*t = SignedMessage{}
br := cbg.GetPeeker(r)
scratch := make([]byte, 8)
maj, extra, err := cbg.CborReadHeaderBuf(br, scratch)
if err != nil {
return err
}
if maj != cbg.MajArray {
return fmt.Errorf("cbor input should be of type array")
}
if extra != 2 {
return fmt.Errorf("cbor input had wrong number of fields")
}
{
if err := t.Message.UnmarshalCBOR(br); err != nil {
return fmt.Errorf("unmarshaling t.Message: %w", err)
}
}
{
if err := t.Signature.UnmarshalCBOR(br); err != nil {
return fmt.Errorf("unmarshaling t.Signature: %w", err)
}
}
return nil
}
var lengthBufSignedMessage = []byte{130}
func (t *SignedMessage) MarshalCBOR(w io.Writer) error {
if t == nil {
_, err := w.Write(cbg.CborNull)
return err
}
if _, err := w.Write(lengthBufSignedMessage); err != nil {
return err
}
if err := t.Message.MarshalCBOR(w); err != nil {
return err
}
if err := t.Signature.MarshalCBOR(w); err != nil {
return err
}
return nil
}

View File

@ -1,12 +1,12 @@
package rpc package rpc
var rpcs = map[uint8]map[string]func(string) (string, error){} // rpcType -> {rpcMethodName -> actual func var} var rpcs = map[uint8]map[string]func(string) ([]byte, error){} // rpcType -> {rpcMethodName -> actual func var}
func RegisterRPC(rpcType uint8, rpcMethods map[string]func(string) (string, error)) { func RegisterRPC(rpcType uint8, rpcMethods map[string]func(string) ([]byte, error)) {
rpcs[rpcType] = rpcMethods rpcs[rpcType] = rpcMethods
} }
func GetRPCMethod(rpcType uint8, rpcMethodName string) func(string) (string, error) { func GetRPCMethod(rpcType uint8, rpcMethodName string) func(string) ([]byte, error) {
rpcMethods, ok := rpcs[rpcType] rpcMethods, ok := rpcs[rpcType]
if !ok { if !ok {
return nil return nil

View File

@ -39,7 +39,7 @@ func NewSolanaClient() *SolanaClient {
} }
} }
func (c *SolanaClient) GetTransaction(txHash string) (string, error) { func (c *SolanaClient) GetTransaction(txHash string) ([]byte, error) {
req := fasthttp.AcquireRequest() req := fasthttp.AcquireRequest()
req.SetRequestURI(c.url) req.SetRequestURI(c.url)
req.Header.SetMethod("POST") req.Header.SetMethod("POST")
@ -48,18 +48,18 @@ func (c *SolanaClient) GetTransaction(txHash string) (string, error) {
requestBody.Params = append(requestBody.Params, txHash, "json") requestBody.Params = append(requestBody.Params, txHash, "json")
body, err := json.Marshal(requestBody) body, err := json.Marshal(requestBody)
if err != nil { if err != nil {
return "", fmt.Errorf("Failed to marshal request body %v", err) return nil, fmt.Errorf("Failed to marshal request body %v", err)
} }
req.AppendBody(body) req.AppendBody(body)
resp := fasthttp.AcquireResponse() resp := fasthttp.AcquireResponse()
client := &fasthttp.Client{} client := &fasthttp.Client{}
if err = client.Do(req, resp); err != nil { if err = client.Do(req, resp); err != nil {
logrus.Warn("Failed to construct solana node rpc request", err) logrus.Warn("Failed to construct solana node rpc request", err)
return "", err return nil, err
} }
bodyBytes := resp.Body() bodyBytes := resp.Body()
logrus.Info(string(bodyBytes)) logrus.Info(string(bodyBytes))
return string(bodyBytes), nil return bodyBytes, nil
} }
func (c *SolanaClient) subscribeOnProgram(programID string) { func (c *SolanaClient) subscribeOnProgram(programID string) {

View File

@ -32,8 +32,12 @@ func (ed25519Signer) Sign(p []byte, msg []byte) ([]byte, error) {
return ed25519.Sign(privKey, msg), nil return ed25519.Sign(privKey, msg), nil
} }
func (ed25519Signer) Verify(sig []byte, a peer.ID, msg []byte) error { func (ed25519Signer) Verify(sig []byte, a []byte, msg []byte) error {
pubKey, err := a.ExtractPublicKey() id, err := peer.IDFromBytes(a)
if err != nil {
return err
}
pubKey, err := id.ExtractPublicKey()
if err != nil { if err != nil {
return err return err
} }

64
sigs/secp/secp.go Normal file
View File

@ -0,0 +1,64 @@
package secp
import (
"fmt"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-crypto"
"github.com/minio/blake2b-simd"
"github.com/Secured-Finance/dione/sigs"
"github.com/Secured-Finance/dione/types"
)
type secpSigner struct{}
func (secpSigner) GenPrivate() ([]byte, error) {
priv, err := crypto.GenerateKey()
if err != nil {
return nil, err
}
return priv, nil
}
func (secpSigner) ToPublic(pk []byte) ([]byte, error) {
return crypto.PublicKey(pk), nil
}
func (secpSigner) Sign(pk []byte, msg []byte) ([]byte, error) {
b2sum := blake2b.Sum256(msg)
sig, err := crypto.Sign(pk, b2sum[:])
if err != nil {
return nil, err
}
return sig, nil
}
func (secpSigner) Verify(sig []byte, a []byte, msg []byte) error {
b2sum := blake2b.Sum256(msg)
pubk, err := crypto.EcRecover(b2sum[:], sig)
if err != nil {
return err
}
maybeaddr, err := address.NewSecp256k1Address(pubk)
if err != nil {
return err
}
actualAddr, err := address.NewSecp256k1Address(a)
if err != nil {
return err
}
if actualAddr != maybeaddr {
return fmt.Errorf("signature did not match")
}
return nil
}
func init() {
sigs.RegisterSignature(types.SigTypeSecp256k1, secpSigner{})
}

View File

@ -4,8 +4,6 @@ import (
"context" "context"
fmt "fmt" fmt "fmt"
"github.com/libp2p/go-libp2p-core/peer"
"github.com/Secured-Finance/dione/types" "github.com/Secured-Finance/dione/types"
"github.com/filecoin-project/go-address" "github.com/filecoin-project/go-address"
"golang.org/x/xerrors" "golang.org/x/xerrors"
@ -30,7 +28,7 @@ func Sign(sigType types.SigType, privkey []byte, msg []byte) (*types.Signature,
} }
// Verify verifies signatures // Verify verifies signatures
func Verify(sig *types.Signature, addr peer.ID, msg []byte) error { func Verify(sig *types.Signature, addrByte []byte, msg []byte) error {
if sig == nil { if sig == nil {
return xerrors.Errorf("signature is nil") return xerrors.Errorf("signature is nil")
} }
@ -40,7 +38,7 @@ func Verify(sig *types.Signature, addr peer.ID, msg []byte) error {
return fmt.Errorf("cannot verify signature of unsupported type: %v", sig.Type) return fmt.Errorf("cannot verify signature of unsupported type: %v", sig.Type)
} }
return sv.Verify(sig.Data, addr, msg) return sv.Verify(sig.Data, addrByte, msg)
} }
// Generate generates private key of given type // Generate generates private key of given type
@ -92,7 +90,7 @@ type SigShim interface {
GenPrivate() ([]byte, error) GenPrivate() ([]byte, error)
ToPublic(pk []byte) ([]byte, error) ToPublic(pk []byte) ([]byte, error)
Sign(pk []byte, msg []byte) ([]byte, error) Sign(pk []byte, msg []byte) ([]byte, error)
Verify(sig []byte, a peer.ID, msg []byte) error Verify(sig []byte, a []byte, msg []byte) error
} }
var sigs map[types.SigType]SigShim var sigs map[types.SigType]SigShim

View File

@ -14,7 +14,9 @@ type SigType byte
const ( const (
SigTypeUnknown = SigType(math.MaxUint8) SigTypeUnknown = SigType(math.MaxUint8)
SigTypeEd25519 = SigType(iota) SigTypeSecp256k1 = SigType(iota)
SigTypeBLS
SigTypeEd25519
) )
func (t SigType) Name() (string, error) { func (t SigType) Name() (string, error) {
@ -23,6 +25,10 @@ func (t SigType) Name() (string, error) {
return "unknown", nil return "unknown", nil
case SigTypeEd25519: case SigTypeEd25519:
return "ed25519", nil return "ed25519", nil
case SigTypeSecp256k1:
return "secp256k1", nil
case SigTypeBLS:
return "bls", nil
default: default:
return "", fmt.Errorf("invalid signature type: %d", t) return "", fmt.Errorf("invalid signature type: %d", t)
} }
@ -85,6 +91,10 @@ func (s *Signature) UnmarshalCBOR(br io.Reader) error {
return fmt.Errorf("invalid signature type in cbor input: %d", buf[0]) return fmt.Errorf("invalid signature type in cbor input: %d", buf[0])
case SigTypeEd25519: case SigTypeEd25519:
s.Type = SigTypeEd25519 s.Type = SigTypeEd25519
case SigTypeSecp256k1:
s.Type = SigTypeSecp256k1
case SigTypeBLS:
s.Type = SigTypeBLS
} }
s.Data = buf[1:] s.Data = buf[1:]
return nil return nil
@ -112,6 +122,10 @@ func (s *Signature) UnmarshalBinary(bs []byte) error {
s.Type = SigTypeUnknown s.Type = SigTypeUnknown
case SigTypeEd25519: case SigTypeEd25519:
s.Type = SigTypeEd25519 s.Type = SigTypeEd25519
case SigTypeSecp256k1:
s.Type = SigTypeSecp256k1
case SigTypeBLS:
s.Type = SigTypeBLS
} }
s.Data = bs[1:] s.Data = bs[1:]
return nil return nil