github.com/bigzoro/my_simplechain@v0.0.0-20240315012955-8ad0a2a29bb9/consensus/hotstuff/api.go (about)

     1  package hotstuff
     2  
     3  import (
     4  	"encoding/binary"
     5  	"errors"
     6  	"fmt"
     7  
     8  	"github.com/bigzoro/my_simplechain/common/hexutil"
     9  	"github.com/bigzoro/my_simplechain/consensus"
    10  	bls "github.com/bigzoro/my_simplechain/consensus/hotstuff/bls12-381"
    11  	"github.com/bigzoro/my_simplechain/consensus/hotstuff/common"
    12  	"github.com/bigzoro/my_simplechain/rpc"
    13  )
    14  
    15  type replica struct {
    16  	ID     uint32
    17  	Pubkey hexutil.Bytes
    18  }
    19  
    20  // API is a user facing RPC API to send requests for replicas joining/removing to the
    21  // Hotstuff network
    22  type API struct {
    23  	chain   consensus.ChainReader
    24  	council *Council
    25  }
    26  
    27  func (api *API) Add(expire rpc.BlockNumber, id uint32, pkbytes hexutil.Bytes, sigbytes hexutil.Bytes) error {
    28  	if header := api.chain.CurrentHeader(); uint64(expire) <= header.Number.Uint64() {
    29  		return fmt.Errorf("expired event for %d/%d", expire, header.Number.Uint64())
    30  	}
    31  
    32  	ev := &event{
    33  		kind:   replicaJoined,
    34  		expire: uint64(expire),
    35  	}
    36  	ev.id.SetUint32(id)
    37  	ev.pubkey = new(bls.PublicKey)
    38  	if err := ev.pubkey.FromBytes(pkbytes); err != nil {
    39  		return err
    40  	}
    41  	ev.sig = new(bls.AggregateSignature)
    42  	if err := ev.sig.FromBytes(sigbytes); err != nil {
    43  		return err
    44  	}
    45  	return api.council.navigation.add(ev)
    46  }
    47  
    48  func (api *API) Remove(expire rpc.BlockNumber, id uint32, sigbytes hexutil.Bytes) error {
    49  	if header := api.chain.CurrentHeader(); uint64(expire) <= header.Number.Uint64() {
    50  		return fmt.Errorf("expired event for %d/%d", expire, header.Number.Uint64())
    51  	}
    52  
    53  	ev := &event{
    54  		kind:   replicaRemoved,
    55  		expire: uint64(expire),
    56  	}
    57  	ev.id.SetUint32(id)
    58  	ev.sig = new(bls.AggregateSignature)
    59  	if err := ev.sig.FromBytes(sigbytes); err != nil {
    60  		return err
    61  	}
    62  	return api.council.navigation.add(ev)
    63  }
    64  
    65  func (api *API) ProposeAdd(expire rpc.BlockNumber, id uint32, pkbytes hexutil.Bytes) (hexutil.Bytes, error) {
    66  	raw := make([]byte, 8)
    67  	binary.LittleEndian.PutUint64(raw, uint64(expire))
    68  
    69  	hotsid := new(common.ID)
    70  	hotsid.SetUint32(id)
    71  
    72  	sig, err := api.council.Sign(legacyCypherDigest([]byte{replicaJoined}, raw, hotsid.Bytes(), pkbytes).Bytes())
    73  	if err != nil {
    74  		return nil, err
    75  	}
    76  	return sig.ToBytes()
    77  }
    78  
    79  func (api *API) ProposeRemove(expire rpc.BlockNumber, id uint32) (hexutil.Bytes, error) {
    80  	raw := make([]byte, 8)
    81  	binary.LittleEndian.PutUint64(raw, uint64(expire))
    82  
    83  	hotsid := new(common.ID)
    84  	hotsid.SetUint32(id)
    85  
    86  	sig, err := api.council.Sign(legacyCypherDigest([]byte{replicaRemoved}, raw, hotsid.Bytes()).Bytes())
    87  	if err != nil {
    88  		return nil, err
    89  	}
    90  	return sig.ToBytes()
    91  }
    92  
    93  func (api *API) GetReplicaInfo(expire rpc.BlockNumber) ([]replica, error) {
    94  	header := api.chain.GetHeaderByNumber(uint64(expire))
    95  	if header == nil {
    96  		return nil, errors.New("unknown block")
    97  	}
    98  
    99  	snaphash, err := extractSnapshot(header, true)
   100  	if err != nil {
   101  		return nil, err
   102  	}
   103  	snap, err := api.council.snapshot(snaphash)
   104  	if err != nil {
   105  		return nil, err
   106  	}
   107  
   108  	reps := make([]replica, 0, len(snap.Idset))
   109  	for i := range snap.Idset {
   110  		reps = append(reps, replica{
   111  			ID:     snap.Idset[i].Uint32(),
   112  			Pubkey: hexutil.Bytes(snap.Pubkeys[snap.Idset[i]].ToBytes()),
   113  		})
   114  	}
   115  
   116  	return reps, nil
   117  }
   118  
   119  func (api *API) Aggregate(mulSigbytes []hexutil.Bytes) (hexutil.Bytes, error) {
   120  	sigs := make([]*bls.PartialSignature, 0, len(mulSigbytes))
   121  	for _, sigbytes := range mulSigbytes {
   122  		sig := new(bls.PartialSignature)
   123  		if err := sig.FromBytes(sigbytes); err != nil {
   124  			return nil, err
   125  		}
   126  		sigs = append(sigs, sig)
   127  	}
   128  
   129  	aggr, err := bls.Combine(sigs...)
   130  	if err != nil {
   131  		return nil, err
   132  	}
   133  	return aggr.ToBytes()
   134  }