github.com/okex/exchain@v1.8.0/libs/tendermint/types/deltas.go (about)

     1  package types
     2  
     3  import (
     4  	"bytes"
     5  	"fmt"
     6  	"time"
     7  
     8  	"github.com/okex/exchain/libs/tendermint/crypto/tmhash"
     9  	"github.com/okex/exchain/libs/tendermint/libs/compress"
    10  	"github.com/tendermint/go-amino"
    11  )
    12  
    13  const (
    14  	FlagDownloadDDS     = "download-delta"
    15  	FlagUploadDDS       = "upload-delta"
    16  	FlagAppendPid       = "append-pid"
    17  	FlagBufferSize      = "delta-buffer-size"
    18  	FlagDDSCompressType = "compress-type"
    19  	FlagDDSCompressFlag = "compress-flag"
    20  
    21  	// redis
    22  	// url fmt (ip:port)
    23  	FlagRedisUrl  = "delta-redis-url"
    24  	FlagRedisAuth = "delta-redis-auth"
    25  	// expire unit: second
    26  	FlagRedisExpire = "delta-redis-expire"
    27  	FlagRedisDB     = "delta-redis-db"
    28  	FlagFastQuery   = "fast-query"
    29  
    30  	// FlagDeltaVersion specify the DeltaVersion
    31  	FlagDeltaVersion = "delta-version"
    32  )
    33  
    34  var (
    35  	// DeltaVersion do not apply delta if version does not match
    36  	// if user specify the flag 'FlagDeltaVersion'(--delta-version) use user's setting,
    37  	// otherwise use the default value
    38  	DeltaVersion = 10
    39  )
    40  
    41  var (
    42  	FastQuery     = false
    43  	DownloadDelta = false
    44  	UploadDelta   = false
    45  	WasmStoreCode = false
    46  )
    47  
    48  type DeltasMessage struct {
    49  	Metadata     []byte `json:"metadata"`
    50  	MetadataHash []byte `json:"metadata_hash"`
    51  	Height       int64  `json:"height"`
    52  	CompressType int    `json:"compress_type"`
    53  	From         string `json:"from"`
    54  }
    55  
    56  func (m *DeltasMessage) AminoSize(_ *amino.Codec) int {
    57  	var size int
    58  	// field 1
    59  	if len(m.Metadata) != 0 {
    60  		size += 1 + amino.ByteSliceSize(m.Metadata)
    61  	}
    62  	// field 2
    63  	if len(m.MetadataHash) != 0 {
    64  		size += 1 + amino.ByteSliceSize(m.MetadataHash)
    65  	}
    66  	// field 3
    67  	if m.Height != 0 {
    68  		size += 1 + amino.UvarintSize(uint64(m.Height))
    69  	}
    70  	// field 4
    71  	if m.CompressType != 0 {
    72  		size += 1 + amino.UvarintSize(uint64(m.CompressType))
    73  	}
    74  	// field 5
    75  	if m.From != "" {
    76  		size += 1 + amino.EncodedStringSize(m.From)
    77  	}
    78  	return size
    79  }
    80  
    81  func (m *DeltasMessage) MarshalToAmino(cdc *amino.Codec) ([]byte, error) {
    82  	var buf bytes.Buffer
    83  	buf.Grow(m.AminoSize(cdc))
    84  	err := m.MarshalAminoTo(cdc, &buf)
    85  	if err != nil {
    86  		return nil, err
    87  	}
    88  	return buf.Bytes(), nil
    89  }
    90  
    91  func (m *DeltasMessage) MarshalAminoTo(_ *amino.Codec, buf *bytes.Buffer) error {
    92  	// field 1
    93  	if len(m.Metadata) != 0 {
    94  		const pbKey = 1<<3 | 2
    95  		if err := amino.EncodeByteSliceWithKeyToBuffer(buf, m.Metadata, pbKey); err != nil {
    96  			return err
    97  		}
    98  	}
    99  	// field 2
   100  	if len(m.MetadataHash) != 0 {
   101  		const pbKey = 2<<3 | 2
   102  		if err := amino.EncodeByteSliceWithKeyToBuffer(buf, m.MetadataHash, pbKey); err != nil {
   103  			return err
   104  		}
   105  	}
   106  	// field 3
   107  	if m.Height != 0 {
   108  		const pbKey = 3 << 3
   109  		if err := amino.EncodeUvarintWithKeyToBuffer(buf, uint64(m.Height), pbKey); err != nil {
   110  			return err
   111  		}
   112  	}
   113  	// field 4
   114  	if m.CompressType != 0 {
   115  		const pbKey = 4 << 3
   116  		if err := amino.EncodeUvarintWithKeyToBuffer(buf, uint64(m.CompressType), pbKey); err != nil {
   117  			return err
   118  		}
   119  	}
   120  	// field 5
   121  	if m.From != "" {
   122  		const pbKey = 5<<3 | 2
   123  		if err := amino.EncodeStringWithKeyToBuffer(buf, m.From, pbKey); err != nil {
   124  			return err
   125  		}
   126  	}
   127  	return nil
   128  }
   129  
   130  func (m *DeltasMessage) UnmarshalFromAmino(_ *amino.Codec, data []byte) error {
   131  	const fieldCount = 5
   132  	var currentField int
   133  	var currentType amino.Typ3
   134  	var err error
   135  
   136  	for cur := 1; cur <= fieldCount; cur++ {
   137  		if len(data) != 0 && (currentField == 0 || currentField < cur) {
   138  			var nextField int
   139  			if nextField, currentType, err = amino.ParseProtoPosAndTypeMustOneByte(data[0]); err != nil {
   140  				return err
   141  			}
   142  			if nextField < currentField {
   143  				return fmt.Errorf("next field should greater than %d, got %d", currentField, nextField)
   144  			} else {
   145  				currentField = nextField
   146  			}
   147  		}
   148  
   149  		if len(data) == 0 || currentField != cur {
   150  			switch cur {
   151  			case 1:
   152  				m.Metadata = nil
   153  			case 2:
   154  				m.MetadataHash = nil
   155  			case 3:
   156  				m.Height = 0
   157  			case 4:
   158  				m.CompressType = 0
   159  			case 5:
   160  				m.From = ""
   161  			default:
   162  				return fmt.Errorf("unexpect feild num %d", cur)
   163  			}
   164  		} else {
   165  			pbk := data[0]
   166  			data = data[1:]
   167  			var subData []byte
   168  			if currentType == amino.Typ3_ByteLength {
   169  				if subData, err = amino.DecodeByteSliceWithoutCopy(&data); err != nil {
   170  					return err
   171  				}
   172  			}
   173  			switch pbk {
   174  			case 1<<3 | byte(amino.Typ3_ByteLength):
   175  				amino.UpdateByteSlice(&m.Metadata, subData)
   176  			case 2<<3 | byte(amino.Typ3_ByteLength):
   177  				amino.UpdateByteSlice(&m.MetadataHash, subData)
   178  			case 3<<3 | byte(amino.Typ3_Varint):
   179  				if uvint, err := amino.DecodeUvarintUpdateBytes(&data); err != nil {
   180  					return err
   181  				} else {
   182  					m.Height = int64(uvint)
   183  				}
   184  			case 4<<3 | byte(amino.Typ3_Varint):
   185  				if m.CompressType, err = amino.DecodeIntUpdateBytes(&data); err != nil {
   186  					return err
   187  				}
   188  			case 5<<3 | byte(amino.Typ3_ByteLength):
   189  				m.From = string(subData)
   190  			default:
   191  				return fmt.Errorf("unexpect pb key %d", pbk)
   192  			}
   193  		}
   194  	}
   195  
   196  	if len(data) != 0 {
   197  		return fmt.Errorf("unexpect data remain %X", data)
   198  	}
   199  
   200  	return nil
   201  }
   202  
   203  type DeltaPayload struct {
   204  	ABCIRsp        []byte
   205  	DeltasBytes    []byte
   206  	WatchBytes     []byte
   207  	WasmWatchBytes []byte
   208  }
   209  
   210  func (payload *DeltaPayload) AminoSize(_ *amino.Codec) int {
   211  	var size int
   212  	// field 1
   213  	if len(payload.ABCIRsp) != 0 {
   214  		size += 1 + amino.ByteSliceSize(payload.ABCIRsp)
   215  	}
   216  	// field 2
   217  	if len(payload.DeltasBytes) != 0 {
   218  		size += 1 + amino.ByteSliceSize(payload.DeltasBytes)
   219  	}
   220  	// field 3
   221  	if len(payload.WatchBytes) != 0 {
   222  		size += 1 + amino.ByteSliceSize(payload.WatchBytes)
   223  	}
   224  	// field 4
   225  	if len(payload.WasmWatchBytes) != 0 {
   226  		size += 1 + amino.ByteSliceSize(payload.WasmWatchBytes)
   227  	}
   228  	return size
   229  }
   230  
   231  func (payload *DeltaPayload) MarshalToAmino(cdc *amino.Codec) ([]byte, error) {
   232  	var buf bytes.Buffer
   233  	buf.Grow(payload.AminoSize(cdc))
   234  	err := payload.MarshalAminoTo(cdc, &buf)
   235  	if err != nil {
   236  		return nil, err
   237  	}
   238  	return buf.Bytes(), nil
   239  }
   240  
   241  func (payload *DeltaPayload) MarshalAminoTo(_ *amino.Codec, buf *bytes.Buffer) error {
   242  	// field 1
   243  	if len(payload.ABCIRsp) != 0 {
   244  		const pbKey = 1<<3 | 2
   245  		if err := amino.EncodeByteSliceWithKeyToBuffer(buf, payload.ABCIRsp, pbKey); err != nil {
   246  			return err
   247  		}
   248  	}
   249  	// field 2
   250  	if len(payload.DeltasBytes) != 0 {
   251  		const pbKey = 2<<3 | 2
   252  		if err := amino.EncodeByteSliceWithKeyToBuffer(buf, payload.DeltasBytes, pbKey); err != nil {
   253  			return err
   254  		}
   255  	}
   256  	// field 3
   257  	if len(payload.WatchBytes) != 0 {
   258  		const pbKey = 3<<3 | 2
   259  		if err := amino.EncodeByteSliceWithKeyToBuffer(buf, payload.WatchBytes, pbKey); err != nil {
   260  			return err
   261  		}
   262  	}
   263  	// field 4
   264  	if len(payload.WasmWatchBytes) != 0 {
   265  		const pbKey = 4<<3 | 2
   266  		if err := amino.EncodeByteSliceWithKeyToBuffer(buf, payload.WasmWatchBytes, pbKey); err != nil {
   267  			return err
   268  		}
   269  	}
   270  	return nil
   271  }
   272  
   273  func (payload *DeltaPayload) UnmarshalFromAmino(_ *amino.Codec, data []byte) error {
   274  	const fieldCount = 4
   275  	var currentField int
   276  	var currentType amino.Typ3
   277  	var err error
   278  
   279  	for cur := 1; cur <= fieldCount; cur++ {
   280  		if len(data) != 0 && (currentField == 0 || currentField < cur) {
   281  			var nextField int
   282  			if nextField, currentType, err = amino.ParseProtoPosAndTypeMustOneByte(data[0]); err != nil {
   283  				return err
   284  			}
   285  			if nextField < currentField {
   286  				return fmt.Errorf("next field should greater than %d, got %d", currentField, nextField)
   287  			} else {
   288  				currentField = nextField
   289  			}
   290  		}
   291  
   292  		if len(data) == 0 || currentField != cur {
   293  			switch cur {
   294  			case 1:
   295  				payload.ABCIRsp = nil
   296  			case 2:
   297  				payload.DeltasBytes = nil
   298  			case 3:
   299  				payload.WatchBytes = nil
   300  			case 4:
   301  				payload.WasmWatchBytes = nil
   302  			default:
   303  				return fmt.Errorf("unexpect feild num %d", cur)
   304  			}
   305  		} else {
   306  			pbk := data[0]
   307  			data = data[1:]
   308  			var subData []byte
   309  			if currentType == amino.Typ3_ByteLength {
   310  				if subData, err = amino.DecodeByteSliceWithoutCopy(&data); err != nil {
   311  					return err
   312  				}
   313  			}
   314  			switch pbk {
   315  			case 1<<3 | byte(amino.Typ3_ByteLength):
   316  				if len(subData) != 0 {
   317  					payload.ABCIRsp = make([]byte, len(subData))
   318  					copy(payload.ABCIRsp, subData)
   319  				} else {
   320  					payload.ABCIRsp = nil
   321  				}
   322  			case 2<<3 | byte(amino.Typ3_ByteLength):
   323  				if len(subData) != 0 {
   324  					payload.DeltasBytes = make([]byte, len(subData))
   325  					copy(payload.DeltasBytes, subData)
   326  				} else {
   327  					payload.DeltasBytes = nil
   328  				}
   329  			case 3<<3 | byte(amino.Typ3_ByteLength):
   330  				if len(subData) != 0 {
   331  					payload.WatchBytes = make([]byte, len(subData))
   332  					copy(payload.WatchBytes, subData)
   333  				} else {
   334  					payload.WatchBytes = nil
   335  				}
   336  			case 4<<3 | byte(amino.Typ3_ByteLength):
   337  				if len(subData) != 0 {
   338  					payload.WasmWatchBytes = make([]byte, len(subData))
   339  					copy(payload.WasmWatchBytes, subData)
   340  				} else {
   341  					payload.WasmWatchBytes = nil
   342  				}
   343  			default:
   344  				return fmt.Errorf("unexpect pb key %d", pbk)
   345  			}
   346  		}
   347  	}
   348  
   349  	if len(data) != 0 {
   350  		return fmt.Errorf("unexpect data remain %X", data)
   351  	}
   352  
   353  	return nil
   354  }
   355  
   356  // Deltas defines the ABCIResponse and state delta
   357  type Deltas struct {
   358  	Height       int64
   359  	Payload      DeltaPayload
   360  	CompressType int
   361  	CompressFlag int
   362  	From         string
   363  
   364  	marshalElapsed  time.Duration
   365  	compressElapsed time.Duration
   366  	hashElapsed     time.Duration
   367  }
   368  
   369  // Size returns size of the deltas in bytes.
   370  func (d *Deltas) Size() int {
   371  	return len(d.ABCIRsp()) + len(d.DeltasBytes()) + len(d.WatchBytes())
   372  }
   373  func (d *Deltas) ABCIRsp() []byte {
   374  	return d.Payload.ABCIRsp
   375  }
   376  
   377  func (d *Deltas) DeltasBytes() []byte {
   378  	return d.Payload.DeltasBytes
   379  }
   380  
   381  func (d *Deltas) WatchBytes() []byte {
   382  	return d.Payload.WatchBytes
   383  }
   384  
   385  func (d *Deltas) WasmWatchBytes() []byte {
   386  	return d.Payload.WasmWatchBytes
   387  }
   388  
   389  func (d *Deltas) MarshalOrUnmarshalElapsed() time.Duration {
   390  	return d.marshalElapsed
   391  }
   392  func (d *Deltas) CompressOrUncompressElapsed() time.Duration {
   393  	return d.compressElapsed
   394  }
   395  func (d *Deltas) HashElapsed() time.Duration {
   396  	return d.hashElapsed
   397  }
   398  
   399  // Marshal returns the amino encoding.
   400  func (d *Deltas) Marshal() ([]byte, error) {
   401  	t0 := time.Now()
   402  
   403  	// marshal to payload bytes
   404  	payload, err := d.Payload.MarshalToAmino(cdc)
   405  	if err != nil {
   406  		return nil, err
   407  	}
   408  
   409  	t1 := time.Now()
   410  	// calc payload hash
   411  	payloadHash := tmhash.Sum(payload)
   412  
   413  	// compress
   414  	t2 := time.Now()
   415  	payload, err = compress.Compress(d.CompressType, d.CompressFlag, payload)
   416  	if err != nil {
   417  		return nil, err
   418  	}
   419  	t3 := time.Now()
   420  
   421  	dt := &DeltasMessage{
   422  		Metadata:     payload,
   423  		Height:       d.Height,
   424  		CompressType: d.CompressType,
   425  		MetadataHash: payloadHash,
   426  		From:         d.From,
   427  	}
   428  
   429  	// marshal to upload bytes
   430  	res, err := dt.MarshalToAmino(cdc)
   431  	t4 := time.Now()
   432  
   433  	d.hashElapsed = t2.Sub(t1)
   434  	d.compressElapsed = t3.Sub(t2)
   435  	d.marshalElapsed = t4.Sub(t0) - d.compressElapsed - d.hashElapsed
   436  
   437  	return res, err
   438  }
   439  
   440  // Unmarshal deserializes from amino encoded form.
   441  func (d *Deltas) Unmarshal(bs []byte) error {
   442  	t0 := time.Now()
   443  	// unmarshal to DeltasMessage
   444  	msg := &DeltasMessage{}
   445  	err := msg.UnmarshalFromAmino(cdc, bs)
   446  	if err != nil {
   447  		return err
   448  	}
   449  
   450  	t1 := time.Now()
   451  	// uncompress
   452  	d.CompressType = msg.CompressType
   453  	msg.Metadata, err = compress.UnCompress(d.CompressType, msg.Metadata)
   454  	if err != nil {
   455  		return err
   456  	}
   457  
   458  	t2 := time.Now()
   459  	// calc payload hash
   460  	payloadHash := tmhash.Sum(msg.Metadata)
   461  	if bytes.Compare(payloadHash, msg.MetadataHash) != 0 {
   462  		return fmt.Errorf("metadata hash is different")
   463  	}
   464  	t3 := time.Now()
   465  
   466  	err = d.Payload.UnmarshalFromAmino(cdc, msg.Metadata)
   467  	t4 := time.Now()
   468  
   469  	d.Height = msg.Height
   470  	d.From = msg.From
   471  
   472  	d.compressElapsed = t2.Sub(t1)
   473  	d.hashElapsed = t3.Sub(t2)
   474  	d.marshalElapsed = t4.Sub(t0) - d.compressElapsed - d.hashElapsed
   475  	return err
   476  }
   477  
   478  func (d *Deltas) String() string {
   479  	return fmt.Sprintf("height<%d>, size<%d>, from<%s>",
   480  		d.Height,
   481  		d.Size(),
   482  		d.From,
   483  	)
   484  }
   485  
   486  func (dds *Deltas) Validate(height int64) bool {
   487  	if dds.Height != height ||
   488  		len(dds.ABCIRsp()) == 0 ||
   489  		len(dds.DeltasBytes()) == 0 {
   490  		return false
   491  	}
   492  	if FastQuery {
   493  		if len(dds.WatchBytes()) == 0 {
   494  			return false
   495  		}
   496  	}
   497  	return true
   498  }