OSDN Git Service

Hulk did something
[bytom/vapor.git] / equity / equity / util / shift.go
1 package equity
2
3 import (
4         "bytes"
5         "encoding/binary"
6         "encoding/hex"
7         "errors"
8
9         "github.com/vapor/protocol/vm"
10
11         "github.com/vapor/equity/compiler"
12 )
13
14 const (
15         firstClauseShift string = "00000000"
16         endingClauseName string = "ending"
17 )
18
19 // Shift statistics contract clause's offset
20 func Shift(contract *compiler.Contract) (map[string]string, error) {
21         clauseMap := make(map[string]string)
22         if len(contract.Clauses) == 1 {
23                 clauseMap[contract.Clauses[0].Name] = firstClauseShift
24                 return clauseMap, nil
25         }
26
27         instructions, err := vm.ParseProgram(contract.Body)
28         if err != nil {
29                 return nil, err
30         }
31
32         var jumpifData [][]byte
33         for i, inst := range instructions {
34                 if inst.Op.String() == "JUMPIF" {
35                         if i > 0 && instructions[i-1].Op.String() == "NOP" {
36                                 continue
37                         }
38                         jumpifData = append([][]byte{inst.Data}, jumpifData...)
39                 }
40         }
41
42         // Check the number of contract's clause
43         if len(contract.Clauses) != len(jumpifData)+1 {
44                 return nil, errors.New("the number of contract's clause is not equal to the number of jumpif instruction")
45         }
46
47         for i, clause := range contract.Clauses {
48                 if i == 0 {
49                         clauseMap[clause.Name] = firstClauseShift
50                         continue
51                 }
52                 clauseMap[clause.Name] = hex.EncodeToString(jumpifData[i-1])
53         }
54
55         var buffer bytes.Buffer
56         if err := binary.Write(&buffer, binary.LittleEndian, uint32(len(contract.Body))); err != nil {
57                 return nil, err
58         }
59         clauseMap[endingClauseName] = hex.EncodeToString(buffer.Bytes())
60
61         return clauseMap, nil
62 }