package equity import ( "bytes" "encoding/binary" "encoding/hex" "errors" "github.com/vapor/protocol/vm" "github.com/vapor/equity/compiler" ) const ( firstClauseShift string = "00000000" endingClauseName string = "ending" ) // Shift statistics contract clause's offset func Shift(contract *compiler.Contract) (map[string]string, error) { clauseMap := make(map[string]string) if len(contract.Clauses) == 1 { clauseMap[contract.Clauses[0].Name] = firstClauseShift return clauseMap, nil } instructions, err := vm.ParseProgram(contract.Body) if err != nil { return nil, err } var jumpifData [][]byte for i, inst := range instructions { if inst.Op.String() == "JUMPIF" { if i > 0 && instructions[i-1].Op.String() == "NOP" { continue } jumpifData = append([][]byte{inst.Data}, jumpifData...) } } // Check the number of contract's clause if len(contract.Clauses) != len(jumpifData)+1 { return nil, errors.New("the number of contract's clause is not equal to the number of jumpif instruction") } for i, clause := range contract.Clauses { if i == 0 { clauseMap[clause.Name] = firstClauseShift continue } clauseMap[clause.Name] = hex.EncodeToString(jumpifData[i-1]) } var buffer bytes.Buffer if err := binary.Write(&buffer, binary.LittleEndian, uint32(len(contract.Body))); err != nil { return nil, err } clauseMap[endingClauseName] = hex.EncodeToString(buffer.Bytes()) return clauseMap, nil }