github.com/amazechain/amc@v0.1.3/internal/api/agg_sign.go (about)

     1  // Copyright 2023 The AmazeChain Authors
     2  // This file is part of the AmazeChain library.
     3  //
     4  // The AmazeChain library is free software: you can redistribute it and/or modify
     5  // it under the terms of the GNU Lesser General Public License as published by
     6  // the Free Software Foundation, either version 3 of the License, or
     7  // (at your option) any later version.
     8  //
     9  // The AmazeChain library is distributed in the hope that it will be useful,
    10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    12  // GNU Lesser General Public License for more details.
    13  //
    14  // You should have received a copy of the GNU Lesser General Public License
    15  // along with the AmazeChain library. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  package api
    18  
    19  import (
    20  	"context"
    21  	"encoding/hex"
    22  	"fmt"
    23  	"github.com/amazechain/amc/common"
    24  	"github.com/amazechain/amc/common/block"
    25  	"github.com/amazechain/amc/common/crypto"
    26  	"github.com/amazechain/amc/common/crypto/bls"
    27  	"github.com/amazechain/amc/common/crypto/bls/blst"
    28  	"github.com/amazechain/amc/common/types"
    29  	"github.com/amazechain/amc/contracts/deposit"
    30  	"github.com/amazechain/amc/internal/consensus"
    31  	"github.com/amazechain/amc/log"
    32  	event "github.com/amazechain/amc/modules/event/v2"
    33  	"github.com/amazechain/amc/modules/rawdb"
    34  	"github.com/amazechain/amc/modules/state"
    35  	"github.com/ledgerwatch/erigon-lib/kv"
    36  	"golang.org/x/crypto/sha3"
    37  )
    38  
    39  var sigChannel = make(chan AggSign, 10)
    40  
    41  var validVerifers = map[string]string{
    42  	"AMC4541Fc1CCB4e042a3BaDFE46904F9D22d127B682": "157aee59b889a8a9e3ecec11e4f79f6c065e3d21c6da2222b916c54f8c820d9c",
    43  	"AMC9BA336835422BAeFc537d75642959d2a866500a3": "00121edadf6e723f2fe8c23d2359f57a7058986a1b8458d23eb29db7204afea7",
    44  	"AMCf13d680bA12717fE27d33caB983c5C755Ff74358": "5de474bbf3fee5dfda9047287f596c6e6c0271876305357e399fffba6a5f9a9f",
    45  	"AMCd1ff88affe38dfb65c621706dff6468ecd418bff": "4c1ad066cc2971c94a8aca6a7d3e4bdd86891922c5b1d39e6d0da8cad9262be4",
    46  	"AMCb9e94477f5f88b5e8da2e97e8506d6e4fcf04e5b": "2c02dd3cf600af9a8567e5cc5ff158c1b89e1f3ea21bff61f505d141a96a60ee",
    47  }
    48  
    49  //type WithCodeAndHash struct {
    50  //	CodeIndex []byte `json:"codeIndex"`
    51  //	Code      []byte `json:"code"`
    52  //	Hash      []byte `json:"hash"`
    53  //}
    54  
    55  //func ExportCodeAndHash(ctx context.Context, db kv.RwDB) (WithCodeAndHash, error) {
    56  //	var result WithCodeAndHash
    57  //	var err error
    58  //	errs := make(chan error, 1)
    59  //	ctx, cancel := context.WithCancel(ctx)
    60  //	defer cancel()
    61  //
    62  //	var wg sync.WaitGroup
    63  //	wg.Add(2)
    64  //	// export header hash
    65  //	go func(ctx context.Context) {
    66  //		defer wg.Done()
    67  //		rtx, err := db.BeginRo(ctx)
    68  //		if nil != err {
    69  //			errs <- err
    70  //			return
    71  //		}
    72  //		defer rtx.Rollback()
    73  //
    74  //		buf := new(bytes.Buffer)
    75  //		hashW := zlib.NewWriter(buf)
    76  //		defer hashW.Close()
    77  //
    78  //		cur, err := rtx.Cursor(modules.HeaderCanonical)
    79  //		if nil != err {
    80  //			errs <- err
    81  //			return
    82  //		}
    83  //		defer cur.Close()
    84  //
    85  //		select {
    86  //		case <-ctx.Done():
    87  //			return
    88  //		default:
    89  //			for k, v, err := cur.First(); k != nil; k, v, err = cur.Next() {
    90  //				if nil != err {
    91  //					errs <- err
    92  //					return
    93  //				}
    94  //				//b, _ := modules.DecodeBlockNumber(k)
    95  //				//h := types.Hash{}
    96  //				//h.SetBytes(v)
    97  //				//log.Tracef("read hash, %d, %v", b, h)
    98  //				hashW.Write(v)
    99  //			}
   100  //
   101  //			if err := hashW.Flush(); nil != err {
   102  //				errs <- err
   103  //				return
   104  //			}
   105  //			result.Hash = buf.Bytes()
   106  //		}
   107  //	}(ctx)
   108  //
   109  //	// export code
   110  //	go func(ctx context.Context) {
   111  //		defer wg.Done()
   112  //		rtx, err := db.BeginRo(ctx)
   113  //		if nil != err {
   114  //			errs <- err
   115  //			return
   116  //		}
   117  //		defer rtx.Rollback()
   118  //
   119  //		cur, err := rtx.Cursor(modules.Code)
   120  //		if nil != err {
   121  //			errs <- err
   122  //			return
   123  //		}
   124  //		defer cur.Close()
   125  //
   126  //		indBuf := new(bytes.Buffer)
   127  //		indW := zlib.NewWriter(indBuf)
   128  //		defer indW.Close()
   129  //		codeBuf := new(bytes.Buffer)
   130  //		codeW := zlib.NewWriter(codeBuf)
   131  //		defer codeW.Close()
   132  //		index := uint64(0)
   133  //
   134  //		select {
   135  //		case <-ctx.Done():
   136  //			return
   137  //		default:
   138  //			for k, v, err := cur.First(); k != nil; k, v, err = cur.Next() {
   139  //				if nil != err {
   140  //					errs <- err
   141  //					return
   142  //				}
   143  //				indW.Write(k)
   144  //				indW.Write(modules.EncodeBlockNumber(index))
   145  //				index += uint64(len(v))
   146  //				indW.Write(modules.EncodeBlockNumber(index))
   147  //				codeW.Write(v)
   148  //			}
   149  //			result.CodeIndex = indBuf.Bytes()
   150  //			result.Code = codeBuf.Bytes()
   151  //		}
   152  //	}(ctx)
   153  //
   154  //	select {
   155  //	case e := <-errs:
   156  //		err = e
   157  //		cancel()
   158  //	default:
   159  //		wg.Wait()
   160  //	}
   161  //	close(errs)
   162  //	log.Tracef("export code and hash: %+v", result)
   163  //	return result, err
   164  //}
   165  
   166  type AggSign struct {
   167  	Number    uint64          `json:"number"`
   168  	StateRoot types.Hash      `json:"stateRoot"`
   169  	Sign      types.Signature `json:"sign"`
   170  	Address   types.Address   `json:"address"`
   171  	PublicKey types.PublicKey `json:"-"`
   172  }
   173  
   174  func (s *AggSign) Check(root types.Hash) bool {
   175  	if s.StateRoot != root {
   176  		return false
   177  	}
   178  	sig, err := bls.SignatureFromBytes(s.Sign[:])
   179  	if nil != err {
   180  		return false
   181  	}
   182  
   183  	pub, err := bls.PublicKeyFromBytes(s.PublicKey[:])
   184  	if nil != err {
   185  		return false
   186  	}
   187  	return sig.Verify(pub, s.StateRoot[:])
   188  }
   189  
   190  func DepositInfo(db kv.RwDB, key types.Address) *deposit.Info {
   191  	var info *deposit.Info
   192  	_ = db.View(context.Background(), func(tx kv.Tx) error {
   193  		info = deposit.GetDepositInfo(tx, key)
   194  		return nil
   195  	})
   196  	return info
   197  }
   198  
   199  func IsDeposit(db kv.RwDB, addr types.Address) (bool, error) {
   200  	tx, err := db.BeginRo(context.Background())
   201  	if nil != err {
   202  		return false, err
   203  	}
   204  	defer tx.Rollback()
   205  
   206  	return rawdb.IsDeposit(tx, addr), nil
   207  }
   208  
   209  func SignMerge(ctx context.Context, header *block.Header, depositNum uint64) (types.Signature, []*block.Verify, error) {
   210  	aggrSigns := make([]bls.Signature, 0)
   211  	verifiers := make([]*block.Verify, 0)
   212  	uniq := make(map[types.Address]struct{})
   213  
   214  LOOP:
   215  	for {
   216  		select {
   217  		case s := <-sigChannel:
   218  			log.Tracef("accept sign, %+v", s)
   219  			if s.Number != header.Number.Uint64() {
   220  				log.Tracef("discard sign: need block number %d, get %d", header.Number.Uint64(), s.Number)
   221  				continue
   222  			}
   223  
   224  			if _, ok := uniq[s.Address]; ok {
   225  				continue
   226  			}
   227  
   228  			if !s.Check(header.Root) {
   229  				log.Tracef("discard sign: sign check failed! %v", s)
   230  				continue
   231  			}
   232  			sig, err := bls.SignatureFromBytes(s.Sign[:])
   233  			if nil != err {
   234  				return types.Signature{}, nil, err
   235  			}
   236  
   237  			aggrSigns = append(aggrSigns, sig)
   238  			verifiers = append(verifiers, &block.Verify{
   239  				Address:   s.Address,
   240  				PublicKey: s.PublicKey,
   241  			})
   242  			uniq[s.Address] = struct{}{}
   243  		case <-ctx.Done():
   244  			break LOOP
   245  		}
   246  	}
   247  	// todo enough sigs check
   248  	// 1
   249  	// uint64(len(aggrSigns)) < depositNum/2
   250  	// uint64(len(aggrSigns)) < 7
   251  	if uint64(len(aggrSigns)) < 3 {
   252  		return types.Signature{}, nil, consensus.ErrNotEnoughSign
   253  	}
   254  
   255  	aggS := blst.AggregateSignatures(aggrSigns)
   256  	var aggSign types.Signature
   257  	copy(aggSign[:], aggS.Marshal())
   258  	return aggSign, verifiers, nil
   259  }
   260  
   261  func MachineVerify(ctx context.Context) error {
   262  	entire := make(chan common.MinedEntireEvent)
   263  	blocksSub := event.GlobalEvent.Subscribe(entire)
   264  	defer blocksSub.Unsubscribe()
   265  
   266  	errs := make(chan error)
   267  	defer close(errs)
   268  
   269  	for {
   270  		select {
   271  		case b := <-entire:
   272  			log.Tracef("machine verify accept entire, number: %d", b.Entire.Entire.Header.Number.Uint64())
   273  			for k, s := range validVerifers {
   274  				go func(seckey string, address string) {
   275  					// recover private key
   276  					sByte, err := hex.DecodeString(seckey)
   277  					if nil != err {
   278  						errs <- err
   279  						return
   280  					}
   281  					var addr types.Address
   282  					if !addr.DecodeString(address) {
   283  						errs <- fmt.Errorf("unvalid address")
   284  						return
   285  					}
   286  
   287  					// before state verify
   288  					var hash types.Hash
   289  					hasher := sha3.NewLegacyKeccak256()
   290  					state.EncodeBeforeState(hasher, b.Entire.Entire.Snap.Items, b.Entire.Codes)
   291  					hasher.(crypto.KeccakState).Read(hash[:])
   292  					if b.Entire.Entire.Header.MixDigest != hash {
   293  						log.Warn("misMatch before state hash", "want:", b.Entire.Entire.Header.MixDigest, "get:", hash, b.Entire.Entire.Header.Number.Uint64())
   294  						return
   295  					}
   296  
   297  					// publicKey
   298  					var bs [32]byte
   299  					copy(bs[:], sByte)
   300  					pri, err := bls.SecretKeyFromRandom32Byte(bs)
   301  					if nil != err {
   302  						errs <- err
   303  						return
   304  					}
   305  
   306  					// Signature
   307  					sign := pri.Sign(b.Entire.Entire.Header.Root[:])
   308  					tmp := AggSign{Number: b.Entire.Entire.Header.Number.Uint64()}
   309  					copy(tmp.StateRoot[:], b.Entire.Entire.Header.Root[:])
   310  					copy(tmp.Sign[:], sign.Marshal())
   311  					copy(tmp.PublicKey[:], pri.PublicKey().Marshal())
   312  					tmp.Address = addr
   313  					// send res
   314  					sigChannel <- tmp
   315  					//log.Tracef("send verify sign, %+v", tmp)
   316  				}(s, k)
   317  			}
   318  		case <-ctx.Done():
   319  			return nil
   320  		case err := <-errs:
   321  			return err
   322  		}
   323  	}
   324  	return nil
   325  }